51Nod 1051 最大子矩阵和(二维最大字段和dp)

来源:互联网 发布:mac分段压缩文件 编辑:程序博客网 时间:2024/05/16 15:04
一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。
例如:3*3的矩阵:

-1 3 -1
2 -1 3
-3 1 2

和最大的子矩阵是:

3 -1
-1 3
1 2
Input
第1行:M和N,中间用空格隔开(2 <= M,N <= 500)。第2 - N + 1行:矩阵中的元素,每行M个数,中间用空格隔开。(-10^9 <= M[i] <= 10^9)
Output
输出和的最大值。如果所有数都是负数,就输出0。

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1051

如果清楚如何求最大字段和(一维),那么二维的就相当简单了

如果不清楚的话,可以看看: http://blog.csdn.net/qq_33850438/article/details/50638748

以下是我写的代码: 

<span style="font-size:24px;">#include"stdio.h"#include"stdlib.h"#include"algorithm"#include"math.h"using namespace std;const int maxn=505;int data[maxn][maxn];long long  sum[maxn]; int m,n;  // 列  行 const long long  INF=1e9; long long MaxSum1(long long sum[],int n) //一维的最大连续和 {long long ans=-INF,s=0;for(int i=1;i<=n;i++){if(s<0)  s=sum[i];else  s+=sum[i];if(s>ans)  ans=s; }return ans;}long long MaxSum2(int n,int m)  //n*m矩阵  2维最大连续和 {long long ans=0;for(int i=1;i<=m;i++)   //应该控制好这些循环,不然很容易乱 {for(int j=1;j<=n;j++)  sum[j]=0;  for(int j=i;j<=m;j++)  {    for(int k=1;k<=n;k++)        sum[k]+=data[k][j];long long tem=MaxSum1(sum,n);ans=max(ans,tem);} }return ans;}int main(){scanf("%d%d",&m,&n);for(int i=1;i<=n;i++)   for(int j=1;j<=m;j++)      scanf("%d",&data[i][j]);printf("%lld\n",MaxSum2(n,m));return 0;}</span>


更高效的代码:

<span style="font-size:24px;">#include <stdio.h>#include <stdlib.h>#include <cstring>#include <algorithm>using namespace std;typedef __int64 ll;const int maxn = 501;ll sum[maxn][maxn];int main(){int m, n, i, j, x;ll res = 0;scanf("%d%d", &m, &n);memset(sum, 0, sizeof(sum));for (i = 1; i <= n; i++)for (j = 1; j <= m; j++){scanf("%d", &x);sum[i][j] = sum[i - 1][j] + x;}for (i = 1; i <= n; i++){for (j = i; j <= n; j++){ll thisSum = 0, maxSum = 0;for (int k = 1; k <= m; k++){thisSum += (sum[j][k] - sum[i - 1][k]);if (thisSum < 0) thisSum = 0;maxSum = max(maxSum, thisSum);}res = max(res, maxSum);}}printf("%lld", res);}</span>

互相学习,共同进步。


0 0
原创粉丝点击