4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
15
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1081
思路:其实就是化二维为一维,可以把有相同行数的每一列的最大值求出来就可以了,每次都要更新
#include<stdio.h> #include<string.h> int a[110][110],dp[110]; int main() { int n; while(~scanf("%d",&n)){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); int ans=-99999999,sum; for(int i=0;i<n;i++){ memset(dp,0,sizeof(dp)); for(int j=i;j<n;j++){ sum=-1; //每列中的元素相加 for(int k=0;k<n;k++) dp[k]+=a[j][k]; //求和最大的那列 for(int k=0;k<n;k++){ if(sum<0) sum=dp[k]; else sum=sum+dp[k]; if(sum>ans) ans=sum; } } } printf("%d\n",ans); } return 0; }
给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。
例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩阵为:
9 2
-4 1
-1 8
其元素总和为15。
1 4 4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
15
解题思路:二维的最大连续和问题.
我们可以通过转化为一维的最大连续和来求解,方法就是用一个辅助数组dp
dp的作用就是将n行的矩阵压缩为一行(累加求和),这样就转化为了一维的最大连续和问题。然后我们对从第i行开始的子矩阵进行枚举即可。
复杂度为O(N*N)
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int a[110][110],dp[110][110]; int main() { int t,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]); int res=-99999999,sum; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ dp[i][j]=dp[i-1][j]+a[i][j]; } } for(int i=0;i<n;i++){ for(int j=i;j<n;j++){ sum=0; for(int k=0;k<m;k++){ if(sum>0){ sum+=dp[j][k]-dp[i-1][k]; }else{ sum=dp[j][k]-dp[i-1][k]; } res=max(res,sum); } } } printf("%d\n",res); } return 0; }