51Nod 1051 最大子矩阵和
题目
一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。
例如:3*3的矩阵:
-1 3 -1
2 -1 3
-3 1 2
和最大的子矩阵是:
3 -1
-1 3
1 2
输入
第1行:M和N,中间用空格隔开(2 <= M,N <= 500)。 第2 - N + 1行:矩阵中的元素,每行M个数,中间用空格隔开。(-10^9 <= M[i] <= 10^9)
输出
输出和的最大值。如果所有数都是负数,就输出0。
输入样例
3 3
-1 3 -1
2 -1 3
-3 1 2
输出样例
7
分析
最大子矩阵,类比一维最大子段和,复杂度n3
代码
1 /**************************** 2 User:Mandy.H.Y 3 Language:c++ 4 Problem:51Nod 5 Algorithm:DP 6 Date:2018.8.15 7 ****************************/ 8 //#include<bits/stdc++.h> 9 #include<cstdio> 10 #include<iomanip> 11 #include<cmath> 12 13 using namespace std; 14 15 const int maxn = 505; 16 //数据范围-- 17 int m,n; 18 long long ans; 19 long long sum[maxn][maxn]; 20 long long t[maxn]; 21 22 char *TT,*mo,but[(1 << 15) + 2]; 23 #define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 15,stdin)),TT == mo)) ? -1 : *TT++) 24 template<class T>inline void read(T &x){ 25 x = 0;bool flag = 0;char ch = getchar(); 26 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 27 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 28 if(flag) x = -x; 29 } 30 31 template<class T>void putch(const T x){ 32 if(x > 9) putch(x / 10); 33 putchar(x % 10 | 48); 34 } 35 36 template<class T>void put(const T x){ 37 if(x < 0) putchar('-'),putch(-x); 38 else putch(x); 39 } 40 41 void file(){ 42 freopen("1051.in","r",stdin); 43 // freopen("1051.out","w",stdout); 44 } 45 46 void readdata(){ 47 read(m);read(n); 48 for(int i = 1;i <= n; ++ i) 49 for(int j = 1;j <= m; ++ j){ 50 long long x;read(x); 51 sum[i][j] = sum[i - 1][j] + x; 52 //只是竖向的一维前缀和,不是二维前缀和 53 } 54 } 55 56 void work(){ 57 ans = 0; 58 //注意题目要求,全是负数输出0,初值赋成0 59 //(1LL << 61)记得是1LL,1默认为int 60 for(int i = 1;i <= n; ++ i)//枚举长的上界 61 for(int j = i;j <= n; ++ j){//枚举长的下界 62 for(int k = 1;k <= m; ++ k){ 63 t[k] = sum[j][k] - sum[i - 1][k]; 64 if(t[k - 1] > 0) t[k] += t[k - 1];//类比一维 65 ans = max(ans,t[k]); 66 } 67 } 68 69 put(ans); 70 } 71 72 int main(){ 73 // file(); 74 readdata(); 75 work(); 76 return 0; 77 }
非做顽石不可,哪管他敬仰暗唾