//二维的不会做啊= = !
题目大意:给定一个含有正数和负数的矩阵,求其子矩阵的和的最大值
解题思路:本题百思不得其解,第一次想用枚举每行每列。但是肯定TLE。
之后搜了答案才做出来,而确定列的范围可以用到最大窜的概念
数据结构:a[108][108] b[108]//b数组用来存第i行~~第j行相对列元素之和
=================================================================
(2)从一维到二维
一维的情况很简单,如何把一维的情况转化为二维情况呢?
例如,对于本题的测试数据:
我们可以每次任选几行,压缩成一行,这样就转化为了一维情况。
例如,我们求1~2行中的最大子矩阵:即矩阵高为2(1~2行),宽为1:4的矩阵,可以先把1~2行相加,得到9 0 -13 2,再求这个单行的最大子段,由此就可以求得1~2行的最大子矩阵。
=================================================================
解法:
1.先枚举i~j行的相对元素之和存于b[]中
1.1.对b进行对大窜的计算(DP算法)
1.1.1 max_sum=max{max_sum, (sum=sum+b[i]<0 ? 0 : sum+b[i]) }
1.1.2 return max_sum
2.回到1.
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <stdio.h>
#include <string.h>
#define N 110
int DP(int *b, int n)
{
int i, sum, max;
max = 0;
sum = 0;
for(i=0;i<n;i++)
{
sum += b[i];
if(sum < 0)
{
sum = 0;
}
max = max > sum ? max : sum;
}
return max;
}
int main()
{
int i, j, k, n, sum, max;
int a[N][N], b[N];
while(scanf("%d", &n) != EOF)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d", &a[i][j]);
}
}
max = 0;
for(i=0;i<n;i++)
{
memset(b, 0, sizeof(b));
for(j=i;j<n;j++)
{
for(k=0;k<n;k++)
{
b[k] += a[j][k];
}
sum = DP(b, n);
max = max > sum ? max : sum;
}
}
printf("%d\n", max);
}
return 0;
}