for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { Sum[i][j] = Sum[i-1][j] + Sum[i][j-1] + A[i][j] - Sum[i-1][j-1]; } }
時間複雜度O(n^4)的解法:數組
有了二維前綴和,就能夠遍歷因此矩形的左上端點和右下端點,找到最大的矩形和。spa
int res = -INF;
for(int x1=0; x1<n; x1++) { for(int y1=0; y1<m; y1++) { for(int x2=x1+1; x2<=n; x2++) { for(int y2=y1+1; y2<=m; y2++) { int t = Sum[x2][y2] - Sum[x1][y2] - Sum[x2][y1] + Sum[x1][y1];//矩形和 畫張圖就能夠理解了 res = res>t ? res : t; } } } }
但用這個方法提交後以後60分。code
int Min = 0 , res = -INF; for(int i=1; i<=n; i++ ){ Min = min( Min, sum[ L-1 ]); res = max( res, sum[ R ] - Min ); }
二維最大區間和:blog
先求每一列的一維區間和,再遍歷行號(0 - n ) , 這時把 行號爲 i - j 的視爲一維區間,再用上面的方法求最大值。it
//代碼實現io
#include<cstdio> #include<algorithm> using namespace std; const int Max_N = 500; const int Max_M = 500; const int INF = 100000; //輸入 int n,m; int A[Max_N+1][Max_M+1]; int f[Max_N+1][Max_M+1];//求一列的前綴和 int sum[Max_N+1]; //求一維最大區間和的方法 void solve() { for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++){ f[i][j] = f[i-1][j] + A[i][j];//一列前綴和 } } int res = -INF; for(int i=0; i<n; i++) { for(int j=i+1; j<=n; j++)//遍歷行號 { for(int k=1; k<=m; k++)//先求一維前綴和 { sum[k] = f[j][k] - f[i][k] + sum[k-1]; } int Min = 0; for(int k=1; k<=m; k++)//求一維最大區間和 { Min = min( Min,sum[k-1] ); res = max( res,sum[k]-Min ); } } } printf("%d\n",res); } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++){ for(int j=1; j<=m; j++){ scanf("%d",&A[i][j]); } } solve(); return 0; }