一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。
例如:3*3的矩阵:
-1 3 -1
2 -1 3
-3 1 2
和最大的子矩阵是:
3 -1
-1 3
1 2
Input
第1行:M和N,中间用空格隔开(2 <= M,N <= 500)。 第2 - N + 1行:矩阵中的元素,每行M个数,中间用空格隔开。(-10^9 <= M[i] <= 10^9)
Output
输出和的最大值。如果所有数都是负数,就输出0。
Input示例
3 3 -1 3 -1 2 -1 3 -3 1 2
Output示例
7
LL a[N][N]; // a[i][j] 代表的第 i 行前j个数的和
a[i][j1] - a[i][j2] 代表的是 第i行 j1+1 到 j2 的连续字段和,这种连续字段和一共 (m+1)*m/2 种。
然后将这些连续字段和看成一个元素,从 第1行 到 第n行 求最大连续字段和。
从所有的最大连续字段和中求得 最大值 就是 最大子矩阵和。
#include <iostream> #include <cstring> using namespace std; typedef long long LL; const int N = 510; LL a[N][N]; // a[i][j] 代表的第 i 行前j个数的和 int main() { int n, m; cin >> m >> n; memset(a, 0, sizeof(a)); // 初始化 for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { cin >> a[i][j]; a[i][j] = a[i][j]+a[i][j-1]; } } int ans = a[1][1]; for(int i=0; i<m; i++) { for(int j=i+1; j<=m; j++) { // i到j 代表的是 每行 i+1 到 j 的连续字段和,这种连续字段和一共 (m+1)*m/2 种 int temp = 0; for(int k=1; k<=n; k++) { //然后将这些连续字段和看成一个元素,从 第1行 到 第n行 求最大连续字段和。 // 从所有的最大连续字段和中求得 最大值 就是 最大子矩阵和。 temp += a[k][j]-a[k][i]; if(temp > ans) { ans = temp; } if(temp < 0) { temp = 0; } } } } cout << ans << endl; return 0; }