【题目描述】
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1×11×1)子矩阵。
比如,如下4×44×4的矩阵
09−4−1−2218−7−6−40021−20−2−7092−62−41−41−180−2
的最大子矩阵是
9−4−121892−41−18
这个子矩阵的大小是1515。
【输入】
输入是一个N×NN×N的矩阵。输入的第一行给出N(0<N≤100)N(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的NN个整数,再从左到右给出第二行的NN个整数……)给出矩阵中的N2N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127][−127,127]。
【输出】
输出最大子矩阵的大小。
【输入样例】
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
【输出样例】
15
先来吐槽一下,这尼玛题目竟然放在贪心的练习题里我也是很懵逼(可能是我太菜了~~)
这题其实是dp里的经典题,不过那个题是一维的,现在变成二维的了
也很简单就是前i-1的最大和,然后只考虑第i个取不取
方程: f[i]=max(f[i-1],f[i-1]+a[i])
如果把二维数组看成是纵向的一维数组和横向的一维数组,就ok了
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int maxsub(int a[],int n) { int i,max=0,b=0; for(i=0; i<n; i++) { if(b > 0) b += a[i]; else b = a[i]; if(b > max) max = b; } return max; } int n,i,j,k,ans,t; int dp[101][101],a[101]; int main() { while(cin>>n) { for(i=0; i<n; i++) for(j=0; j<n; j++) cin>>dp[i][j]; ans = 0; for(i=0; i<n; i++) { memset(a,0,sizeof(a)); for(j=i; j<n; j++) { for(k=0; k<n; k++) a[k] += dp[j][k]; t = maxsub(a,n); if(t > ans) ans = t; } } cout<<ans<<endl; } }