题目连接http://acm.hdu.edu.cn/showproblem.php?pid=1081
这道题一开始以为是一个搜索题,一提搜索我就想到什么dfs bfs等等,还有什么并查集一些还么接触过的东西,所以我刚开始的的时候直接放弃,这个也是比赛之后做的。
后来看了解题报告知道这是个动态规划。是那个我们比较熟悉的那个最大连续字段和问题的扩展。
原动态方程式 dp[i] = dp[i-1] > 0? dp[i-1] + a[i]:a[i];
以上是一维方程。而这道题无非是扩展到了二维;
所谓的二维矩阵的和,接就是一定行数的在n列中最大的和,也就是同列的相同行数的和的最大值。这个行数也就是可以使任意的两行间的数,即i-j行。
而以上的dp[i]是以第 i 个数结尾的最大的和,而在二维中可以是每 i-j 行中捆绑形式第k列结尾的最大的值。
同样还是遍历得到结果、
for(i = 1;i <= n;i++)
{
for(j = i;j<= n;j++)
{}
}
在{}中用一个
for(k = 1;k <= n;k++)
sum[k] += a[j][k];
来储存各行的和。
然后用dp算出即可
代码如下
View Code
#include<stdio.h> #include<string.h> int a[105][105]; int n,dp[105],sum[105]; int DP() { int i; dp[1] = sum[1]; int max; max = dp[1]; for(i = 2;i <= n;i++) { if(dp[i-1] > 0) dp[i] = dp[i-1] + sum[i]; else dp[i] = sum[i]; if(max < dp[i]) max = dp[i]; } return max; } int main() { int i,j,k,res,max; while(scanf("%d",&n) !=EOF) { for(i = 1;i <= n;i++) for(j = 1;j <= n;j++) scanf("%d",a[i]+j); res = 0; for(i = 1;i <= n;i++) { memset(sum,0,sizeof(sum)); for(j = i;j <= n;j++) { for(k = 0;k <= n;k++) sum[k] += a[j][k]; max = DP(); if(res < max) res = max; } } printf("%d\n",res); } return 0; }