http://acm.hdu.edu.cn/showproblem.php?pid=1081
求解最大子矩阵和:把一维的最大子段和加强成二维。
首先计算从k列开始的第i行k到j列的和:
for(int k=1; k<=N; k++){
for(int i=1; i<=N; i++){
for(int j=k; j<=N; j++){
sum[k][i][j] = sum[k][i][j - 1] + a[i][j];
}
}
}
此过程也可以将k优化掉,sum[i][m]-sum[i][n]即可表示原来的sum[m+1][i][n] = =!自己没想到这个优化。
然后就是dp N^2次最大子段和。
AC代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int N,a[110][110],sum[101][101][101],dp[110];
int main(){
// freopen("in.txt", "r", stdin);
while(scanf("%d", &N) != EOF){
for(int i=1; i<=N; i++)
for(int j=1; j<=N; j++)
scanf("%d",&a[i][j]);
int max3 = -INF;
for(int k=1; k<=N; k++){
for(int i=1; i<=N; i++){
for(int j=k; j<=N; j++){
sum[k][i][j] = sum[k][i][j - 1] + a[i][j];
}
}
int max2 = -INF;
for(int j=k; j<=N; j++){
dp[0] = -INF;
int max1 = -INF;
for(int i=1; i<=N; i++){
if(dp[i - 1] < 0)
dp[i] = sum[k][i][j];
else
dp[i] = dp[i - 1] + sum[k][i][j];
max1 = max(max1, dp[i]);
}
max2 = max(max2, max1);
}
max3 = max(max3, max2);
}
cout << max3 << endl;
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 110;
int n,a[MAX][MAX],sum[MAX][MAX];
int main(){
// freopen("in.txt", "r", stdin);
while(scanf("%d",&n) != EOF){
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&a[i][j]);
memset(sum, 0, sizeof(sum));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
sum[i][j] = sum[i][j-1] + a[i][j];
int ans = -1e9;
for(int i=1; i<=n; i++){
for(int j=i; j<=n; j++){
for(int k=1,tmp = 0; k<=n; k++){
if(tmp > 0)
tmp += sum[k][j] - sum[k][i-1];
else
tmp = sum[k][j] - sum[k][i-1];
if(tmp > ans)
ans = tmp;
}
}
}
printf("%d\n",ans);
}
return 0;
}