O(n^3) 必然要讨论每种情况,每行必然要讨论0~0,0~1,0~2,...i~j(0<=i<=j<n)的情况,每行的每种情况都是一个确定的数值,则把n个【f(i,j)】可以看作求一个一维的最长连续子序列,这样讨论每种i,j分部情况,求出对应的一维最长子序列,这些子序列取max,即为题目所要求的最大连续子矩阵
其实我们可以再输入的时候,就把a[i][j]确定为第i行前j个数之和,即为0~j的分步,这样我们以后讨论序列start~end时,只要a[k][end]-a[k][start-1]即为star~endt的情况
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <queue> using namespace std; const int inf = (1<<31)-1; const int MAXN = 1e3+10; int a[MAXN][MAXN]; int main() { int n,tmp; while(~scanf("%d",&n)){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&tmp); a[i][j] = a[i][j-1]+tmp; //a[i][j为第k行前j个和 } } int sum,mmax=-inf; for(int i=1;i<=n;i++){ //end后端 for(int j=1;j<=i;j++){ //start前端 sum = 0; for(int k=1;k<=n;k++){ sum = max(sum,0)+a[k][i]-a[k][j-1]; //一维的求法 mmax = max(mmax,sum); } } } cout<<mmax<<endl; } //cout << "Hello world!" << endl; return 0; }
起始我们讨论start,end的分布时,也可以这么想,我们可以讨论这些序列的长度l,必然为1~n,再讨论这些序列的起始节点j,完全可以确定这个序列的情况了,
start对应j,end对应j+l-1