当前位置:   article > 正文

实验-动态规划(头歌实践教学平台-ACM/ICPC培训)_平台会对你编写的代码进行测试: 测试输入:a[]={1,2,3,4,5},m=5, b[]={2,5

平台会对你编写的代码进行测试: 测试输入:a[]={1,2,3,4,5},m=5, b[]={2,5,7},n=3;

第1关:数塔问题

  • 任务描述
  • 相关知识
  • 编程要求
  • 解题思路:
  • 测试说明

    任务描述

    本关任务:编写用动态规划解决数塔问题。

  • 相关知识

    为了完成本关任务,你需要掌握:动态规划。

    编程要求

    ,

    求上图从顶层到顶层的一个路径,使路径上的数字和最大。要求输出最大的数字和max和数值和最大的路径。

    解题思路:

    原始信息有层数和数塔中的数据,层数用一个整型变量n存储,数塔中的数据用二维数组data,存储成如下的下三角阵:

     
  • 9
  • 12 15
  • 10 6 8
  • 2 18 9 5
  • 19 7 10 4 16
  • d[n][j]=data[n][j], j=1,2,……,n;
  • d[i][j]=max(d[i+1][j],d[i+1][j+1])+data[i][j], i=n-1,n-2,……1,j=1,2,……,i
  • 5
  • 9
  • 12 15
  • 10 6 8
  • 2 18 9 5
  • 19 7 10 4 16
  • max=59
  • 数值和最大的路径是:9->12->10->18->10

测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. 5
  2. 9
  3. 12 15
  4. 10 6 8
  5. 2 18 9 5
  6. 19 7 10 4 16

输出示例:

 
  1. max=59
  2. 数值和最大的路径是:9->12->10->18->10

开始你的任务吧,祝你成功!

  1. #include <stdio.h>
  2. int main(){
  3. int a[50][50][4],i,j,n;
  4. // printf("Please input the number of rows:\n");
  5. // scanf("%d",&n);
  6. n = 5;
  7. i=1;
  8. a[1][1][1]=9;
  9. a[2][1][1]=12, a[2][2][1]=15;
  10. a[3][1][1]=10, a[3][2][1]=6, a[3][3][1]=8;
  11. a[4][1][1]=2, a[4][2][1]=18, a[4][3][1]=9, a[4][4][1]=5;
  12. a[5][1][1]=19, a[5][2][1]=7, a[5][3][1]=10, a[5][4][1]=4, a[5][5][1]=16;
  13. for(i=1;i<=n;i++)
  14. for(j=1; j<=i; j++)
  15. {
  16. a[i][j][2]=a[i][j][1];
  17. a[i][j][3]=0;
  18. }
  19. for(i=n-1; i>=1; i--)
  20. for(j=1; j<=i; j++)
  21. if(a[i+1][j][2]>a[i+1][j+1][2])
  22. {
  23. a[i][j][2] = a[i][j][2] + a[i+1][j][2];
  24. a[i][j][3] = 0;
  25. }
  26. else
  27. {
  28. a[i][j][2] = a[i][j][2] + a[i+1][j+1][2];
  29. a[i][j][3] = 1;
  30. }
  31. printf("max=%d\n",a[1][1][2]);
  32. printf("数值和最大的路径是:");
  33. j=1;
  34. for(i=1;i<=n-1;i++)
  35. {
  36. printf("%d->",a[i][j][1]);
  37. j = j+a[i][j][3];
  38. }
  39. printf("%d\n\n\n",a[n][j][1]);
  40. return 0;
  41. }

第2关:最长公共子序列


任务描述

本关任务:编写用动态规划解决最长公共子序列问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

求字符串序列“ABCDBAB”和“BDCABA”的最长公共子序列

解题思路:

递推关系分析: 设 A=“a0,a1,…,am−1”,B=“b0,b1,…,bn−1”,Z=“z0,z1,…,zk−1” 为它们的最长公共子序列。 有以下结论: 1)如果am−1=bn−1,则zk−1=am−1=bn−1,且“z0,z1,…,zk−2”是“a0,a1,…,am−2”和“b0,b1,…,bn−2”的一个最长公共子序列; 2)如果am−1​=bn−1,则若zk−1​=am−1,蕴涵“z0,z1,…,zk−1”是“a0,a1,…,am−2”和“b0,b1,…,bn−1”的一个最长公共子序列; 3)如果am−1​=bn−1,则若zk−1​=bn−1,蕴涵“z0,z1,…,zk−1”是“a0,a1,…,am−1”和“b0,b1,…,bn−2”的一个最长公共子序列。 定义c[i][j]为序列“a0,a1,…,ai−1”和“b0,b1,…,bj−1”的最长公共子序列的长度,计算c[i][j]可递归地表述如下: 1)c[i][j]=0 如果i=0或j=0; 2)c[i][j]=c[i−1][j−1]+1 如果i,j>0,且a[i−1]=b[j−1]; 3)c[i][j]=max(c[i][j−1],c[i−1][j]) 如果i,j>0,且a[i−1]​=b[j−1]。 由二维数组c的递归定义,c[i][j]的结果依赖于c[i−1][j−1],c[i−1][j]和c[i][j−1]。可以从c[m][n]开始,跟踪c[i][j]结果的产生过程,从而逆向构造出最长公共子序列。

测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. a=“ABCDBAB”
  2. b=“BDCABA”

输出示例:

 
  1. BCBA

开始你的任务吧,祝你成功!

  1. #include "stdio.h"
  2. #include "string.h"
  3. char a[1000]="ABCDBAB";
  4. char b[1000]="BDCABA";
  5. char str[100];
  6. int c[100][100];
  7. int lcs_len()
  8. {
  9. int m,n,i,j,lcs;
  10. m = strlen(a);
  11. n = strlen(b);
  12. for(i=0;i<=m;i++) c[i][0]=0;
  13. for(i=0;i<=n;i++) c[0][i]=0;
  14. for(i=1;i<=m;i++)
  15. for(j=1;j<=n;j++)
  16. {
  17. if(a[i-1]==b[j-1])
  18. c[i][j] = c[i-1][j-1]+1;
  19. else if(c[i-1][j]>=c[i][j-1])
  20. c[i][j] = c[i-1][j];
  21. else
  22. c[i][j] = c[i][j-1];
  23. }
  24. lcs = c[m][n];
  25. return lcs;
  26. }
  27. void build_lcs()
  28. {
  29. int k,i=strlen(a),j=strlen(b);
  30. k = lcs_len();
  31. str[k]=' ';
  32. while(k>0)
  33. if(c[i][j]==c[i-1][j])
  34. i=i-1;
  35. else if(c[i][j]==c[i][j-1])
  36. j=j-1;
  37. else
  38. {
  39. k=k-1;
  40. str[k]=a[i-1];
  41. j=j-1;
  42. }
  43. }
  44. int main()
  45. {
  46. build_lcs();
  47. printf("%s",str);
  48. return 0;
  49. }

第3关:求序列-2 11 -4 13 -5 -2的最大字段和


任务描述

本关任务:编写用动态规划解决最大字段和问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

给定由n个整数(可能为负数)组成的序列:a1,a2,……,an, 求该序列的最大子段和。当所有整数均为负数,定义其最大子段和为0。

解题思路:

定义b[j]=max(a[i]+a[i+1]+…+a[j]),其中1<=i<=j,并且1<=j<=n。那么所求的最大子段和可以表示为max b[j],1<=j<=n。 由b[j]的定义可知,当b[j−1]>0时b[j]=b[j−1]+a[j],否则b[j]=a[j]。故b[j]的动态规划递归表达式为: b[j]=max(b[j−1]+a[j],a[j]),1<=j<=n。

测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. 6
  2. -2 11 -4 13 -5 -2

输出示例:

 
  1. 20

开始你的任务吧,祝你成功!

  1. #include <stdio.h>
  2. int maxsubsequence(int n,int a[],int b[],int max)
  3. {
  4. for (int i = 0; i < n; i++)
  5. {
  6. if (i == 0)
  7. {
  8. b[i] = a[i];
  9. max = b[i];
  10. }
  11. else
  12. {
  13. if (b[i - 1] <= 0)
  14. b[i] = a[i];
  15. else
  16. b[i] = b[i - 1] + a[i];
  17. if (b[i] > max)
  18. max = b[i];
  19. }
  20. }
  21. return max;
  22. }
  23. int main()
  24. {
  25. int n;
  26. scanf("%d",&n);
  27. int a[1000];
  28. for (int i = 0; i < n; i++)
  29. scanf("%d",&a[i]);
  30. int b[100],max = 0;
  31. max = maxsubsequence(n, a, b, max);
  32. printf("%d",max);
  33. }

第4关:求最长的单调递增子序列长度


任务描述

本关任务:编写用动态规划解决求最长的单调递增子序列长度问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

给定一个长度为n的数组,找出一个最长的单调递增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为7的数组A5,6,7,1,2,8,9,则其最长的单调递增子序列为5,6,7,8,9,长度为5。求318714101223411624的最长的单调递增子序列长度。

解题思路:

设长度为n的数组为(a[0],a[1],a[2],...,a[n−1]),则假定以a[j]结尾的数组序列的最长递增子序列长度为L(j),则L(j)=max(L(i))+1,i<j且a[i]<a[j]。也就是说,我们需要遍历在j之前的所有位置i(从0到j−1),找出满足条件a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的值。最后,我们遍历所有的L(j)(从0到n−1),找出最大值即为最大递增子序列。

测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. 10
  2. 3 18 7 14 10 12 23 41 16 24

输出示例:

 
  1. 6

开始你的任务吧,祝你成功!

  1. #include <stdio.h>
  2. /********** Begin **********/
  3. int main(){
  4. int n;
  5. scanf("%d",&n);
  6. int m[n][3];
  7. m[0][1]=1;
  8. m[0][2]=0;
  9. for(int i=0;i<n;i++){
  10. scanf("%d",&m[i][0]);
  11. if(i!=0){
  12. m[i][1]=0;
  13. int k=i-1;
  14. while(k>=0){
  15. if(m[i][0]>m[k][0]){
  16. if(k==i-1){
  17. m[i][1]=m[k][1]+1;
  18. m[i][2]=k;
  19. }
  20. else{
  21. int max=m[k][1]+1;
  22. if(max>m[i][1]){
  23. m[i][1]=max;
  24. m[i][2]=k;
  25. }
  26. }
  27. }
  28. k--;
  29. }
  30. if(k<0&&m[i][1]==0){
  31. m[i][1]=1;
  32. m[i][2]=i;
  33. }
  34. }
  35. }
  36. int max=m[0][1],j=0;
  37. for(int i=0;i<n;i++){
  38. if(m[i][1]>=max){
  39. max=m[i][1];
  40. j=i;
  41. }
  42. }
  43. printf("%d\n",max);
  44. }
  45. /********** End **********/
  • 第5关:矩阵连乘问题

    • 任务描述
    • 相关知识
    • 编程要求
    • 测试说明

    • 任务描述

      本关任务:编写用动态规划解决矩阵连乘问题。

      相关知识

      为了完成本关任务,你需要掌握:动态规划。

      编程要求

      将矩阵连乘积AiAi+1…Aj简记为A[i:j],其中i<=j。设在矩阵Ak和Ak+1之间将矩阵链断开,则其相应加括号为(AiAi+1…Ak) (Ak+1Ak+2…Aj)。A[i:j]的计算量等于三部分计算量之和: (1)A[i:k]的计算量, (2)A[k+1:j]的计算量, (3)A[i:k]与A[k+1:j]相乘的计算量。 设计算A[i:j]所需最少乘积数目为,则原问题的最优值为。 当i=j时,a[i:j]=Ai​,因此,m[i][j]=0,i=1,⋅⋅⋅,n 当i<j时,m[i][j]=i<k<jmin​{m[i][k]+m[k+1][j]+pi−1​pk​pj​} 其中,矩阵Ai​的矩阵数为pi−1​×pi​ 矩阵A1​的维度:p0​p1​=3035 矩阵A2​的维度:p1​p2​=3515 矩阵A3​的维度:p2​p3​=155 矩阵A4​的维度:p3​p4​=510 矩阵A5​的维度:p4​p5​=1020 矩阵A6​的维度:p5​p6​=2025 求这6个矩阵连乘的最小相乘次数。

      测试说明

      平台会对你编写的代码进行测试:

      测试输入:

       
  • 6
  • 30 35
  • 35 15
  • 15 5
  • 5 10
  • 10 20
  • 输出示例:

     
  • m[1][6]=15125
  • 20 25
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. /********** Begin **********/
    4. int main(){
    5. int n;
    6. scanf("%d",&n);
    7. int a[n][2];
    8. int b[n][n]={0};
    9. for(int i=0;i<n;i++){
    10. scanf("%d %d",&a[i][0],&a[i][1]);
    11. }
    12. for(int i=1;i<n;i++){
    13. for(int j=0;j<n-i;j++){
    14. b[j][j+i]=b[j][j]+b[j+1][j+i]+a[j][0]*a[j][1]*a[j+i][1];
    15. int k=j+1;
    16. for(;k<j+i;k++){
    17. int t=b[j][k]+b[k+1][j+i]+a[j][0]*a[k][1]*a[j+i][1];
    18. if(t<b[j][j+i]) {
    19. b[j][j+i]=t;
    20. }
    21. }
    22. }
    23. }
    24. printf("m[%d][%d]=%d",1,n,b[0][n-1]);
    25. return 0;
    26. }
    27. /********** End **********/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/538245
推荐阅读
相关标签
  

闽ICP备14008679号