题目描述
蒜头君拿到了一个矩阵,他想知道其中的最大非空子矩阵和是多少。
输入格式
第一行输入两个整数 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 }
-
来源:https://www.cnblogs.com/jiamian/p/12204016.html