最大子矩阵和(二维矩阵转一维DP)
题目描述
蒜头君拿到了一个矩阵,他想知道其中的最大非空子矩阵和是多少。
输入格式
第一行输入两个整数 n,m代表这个矩阵的行数和列数。接下来n行,每行m个整数 ai1,ai2,ai3⋯aim。(1≤m,n≤400,−109≤aij≤109)
输出格式
输出一个整数,代表最大非空子矩阵和,占一行。
样例输入
3 3 1 -2 3 -4 5 -6 7 -8 9
样例输出
9
与最大子段和类似,不过上升到了二维,那么我们可以通过枚举上下边界将题目转化为一维的,通过前缀和又可以快速算出固定一列从一行到某一行所有数的和。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const double PI = acos(-1); 17 const double eps =1e-8; 18 #define Bug cout<<"---------------------"<<endl 19 const int maxn=1e5+10; 20 using namespace std; 21 22 LL sum[405][405];//sum[j][i]表示第j列前i行的前缀和 23 LL MAX=-INF;//别忘了初始化 24 25 int main() 26 { 27 int n,m; 28 scanf("%d %d",&n,&m); 29 for(int i=1;i<=n;i++) 30 { 31 for(int j=1;j<=m;j++) 32 { 33 LL x; 34 scanf("%lld",&x); 35 MAX=max(MAX,x); 36 sum[j][i]=sum[j][i-1]+x; 37 } 38 } 39 if(MAX>=0)//如果MAX小于零则直接输出即可 40 { 41 for(int i=1;i<=n;i++)//i为矩阵上边界 42 { 43 for(int k=i;k<=n;k++)//k为矩阵下边界 44 { 45 long long t=0;//和 46 for(int j=1;j<=m;j++)//一维最大子段和(利用列的前缀和快速计算) 47 { 48 if(t+sum[j][k]-sum[j][i-1]<0) t=0; 49 else t+=sum[j][k]-sum[j][i-1]; 50 MAX=max(MAX,t); 51 } 52 } 53 } 54 } 55 printf("%lld\n",MAX); 56 return 0; 57 }
-