1051 最大子矩阵和

一个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;
}


猜你喜欢

转载自blog.csdn.net/qq_38737992/article/details/80092522