HDU1081——To The Max

//二维的不会做啊= = !

题目大意:给定一个含有正数和负数的矩阵,求其子矩阵的和的最大值

解题思路:本题百思不得其解,第一次想用枚举每行每列。但是肯定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.

 

View Code
#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;
}


posted @ 2011-11-29 10:25  1050768624  阅读(674)  评论(0编辑  收藏  举报