【动态规划】最大连续序列和最大子矩阵
一开始接触的动态规划题目就是在杭电OJ上的1003 Max Sum,求一个数列的最大连续子序列,当时花了好长时间才弄懂。后来接触到更多的动态规划题目,就愈发头晕了。
Max Sum 这题应该是很基础吧,状态转移方程为:DP[i]=Max{num[i],DP[i-1]+num[i]} 其中DP[i]表示的是以i位置结束的最大连续子序列的和。如果DP[i-1]<0,也就是说 DP[i-1]+num[i]<num[i],那么最大的序列和就更新为num[i]。具体的代码如下:
1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4 int main()
5 {
6 int t,n;
7 int i,j;
8 int start,end,p,max,num,sum;
9 scanf("%d",&t);
10 for(i=1;i<=t;i++)
11 {
12 p=1;sum=0;
13 max=INT_MIN;
14 scanf("%d",&n);
15 for(j=1;j<=n;j++)
16 {
17 scanf("%d",&num);
18 sum+=num;
19 if(sum>max)
20 {
21 max=sum;
22 start=p;
23 end=j;
24 }
25 if(sum<0)
26 {
27 p=j+1;
28 sum=0;
29 }
30 }
31 printf("Case %d:\n",i);
32 printf("%d %d %d\n",max,start,end);
33 if(i!=t)
34 printf("\n");
35 }
36 return 0;
37 }
基础的问题解决了,那接下来就要面对难一点的了。HDOJ 1081 给你一个矩阵,要你求出最大的子矩阵,所谓最大子矩阵就是:sub-rectangle with the largest sum。这是一个一维扩展到二维的问题,我们可以转化为一维的问题来解决:
详细的思路已经在注释里面写了
1 //求数列最大连续和的扩展 是个好题
2 //HDU 1081 动态规划 从一维到二维 从二维转换为一维
3 #include<iostream>
4 using namespace std;
5 int line(int *a,int n)//求一维数列的最大连续和
6 {
7 int i,Max=a[0],sum=a[0];
8 for(i=1;i<n;i++)
9 {
10 if(sum>0)
11 sum+=a[i];
12 else
13 sum=a[i];
14 if(Max<sum)
15 Max=sum;
16 }
17 return Max;
18 }
19 int n,num[101][101],b[101];
20
21 int main()
22 {
23 int i,j,k,Max,s;
24 while(scanf("%d",&n)==1)
25 {
26 for(i=0;i<n;i++)
27 for(j=0;j<n;j++)
28 scanf("%d",&num[i][j]);
29 s=-10000000;
30 for(i=0;i<n;i++)//i为起始行号
31 {
32 for(k=0;k<n;k++) b[k]=0; //每个状态 阶段 都将数列b初始化
33 for(j=i;j<n;j++)//这个循环 表示当前求的是i--j 的范围 j为结束行
34 {
35 for(k=0;k<n;k++) b[k]+=num[j][k]; //这是将之前的行与当前行累加,是二维转换为一维
36 Max=line(b,n); //求单个数列的最大连续和
37 if(Max>s)
38 s=Max;//记录最大值
39 }
40 }
41 printf("%d\n",s);//得到最大子矩阵的和
42 }
43 return 0;
44 }

浙公网安备 33010602011771号