求矩阵的最大子矩阵
DP典型例题:
Pku 1050 To The Max http://acm.pku.edu.cn/JudgeOnline/problem?id=1050
Hdu 1081 To The Max http://acm.hdu.edu.cn/showproblem.php?pid=1081
题目的意思很简单,在一个矩阵里面找它的子矩阵,使得子矩阵数值之和到达最大。其实就是最大子段和问题在二维空间上的推广。考察下面题目中的例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 7
-1 8 0 -2
我们分别用i j表示起始行和终止行,遍历所有的可能:
for(i=1;i<=n;i++)
for(j=i;j<=n;j++) {}
我们考察其中一种情况 i=2 j=4,这样就相当与选中了2 3 4三行,求那几列的组合能获得最大值,由于总是 2 3 4行,所以我们可以将这3行”捆绑”起来,变为求 4(9-4-1),11(8+2+1),-10(-6-4+0),7(7+2-2)的最大子段和,ok,问题成功转化为一维的情况!
- #include <iostream>
- using namespace std;
- int a[102][102],b[102];
- int f[10002];
- int main()
- {
- int i,j,n,k,m,t,l,q;
- int maxnum, max1;
- while (scanf("%d",&n)!=EOF)
- {
- for (i=0;i<n;i++)
- {
- for (j=0;j<n;j++)
- {
- scanf("%d",&a[i][j]);
- }
- }
- max1 = 0;
- for (i=0;i<n;i++)
- {
- for (j=0;j<n;j++)
- {
- if (i == j) //只有一行的情况,我们只单纯地抽取这行
- {
- for (k=0;k<n;k++)
- {
- b[k] = a[i][k];
- }
- }
- else //如果有多行,那么捆绑每一列的和,使之成为一行
- {
- for (k=0;k<n;k++)
- {
- b[k] = 0;
- for (l=i;l<=j;l++)
- {
- b[k] += a[l][k];
- }
- }
- }
- int sum=0;
- maxnum=-1001;
- int first =0;
- int last = 0;
- int temp = 0;
- for (k=0;k<n;k++)
- {
- sum += b[k];
- if (sum > maxnum)
- {
- maxnum = sum;
- first = temp;
- last = k;
- }
- if (sum < 0)
- {
- sum = 0;
- temp = k+1;
- }
- }//for
- if (maxnum > max1)
- {
- max1 = maxnum;
- }
- }
- }
- printf("%d\n",max1);
- }
- return 0;
- }