最大子矩阵和(二维矩阵转一维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
",MAX);
56     return 0;
57 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12204016.html