题目链接

题目描述
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。

其中,A的子矩阵指在A中行和列均连续的一块。

样例说明
取最后一列,和为10。
数据规模和约定
对于100%的数据,1< =n, m< =500,A中每个元素的绝对值不超过5000。

输入
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。

输出
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。

样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8

样例输出
10

分析:
可以将矩阵进行压缩,用当前矩阵的第i行来表示原来矩阵的前i行,这样的话在计算的时候就可以将二维的矩阵压缩成一维来进行,每次进行相应的行距的变化来变化列的数目。

代码:

#include<iostream>
#include<stdio.h>
using namespace std;
long long A[505][505],B[505][505];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                scanf("%lld",&A[i][j]);
            }

            //矩阵转换,将矩阵的第j列的值转换为前j列值的和
        for(int j=1; j<=m; j++)
        {
            long long int temp=0;
            for(int i=1; i<=n; i++)
            {
                temp+=A[i][j];
                B[i][j]=temp;
            }
        }


        long long int maxSum=-10000000;
        //子矩阵相加的时候,i和j来控制行数,k来控制列数
        for(int i=1; i<=n; i++)
            for(int j=i; j<=n; j++)
            {
                long long int tempSum=0;
                for(int k=1; k<=m; k++)
                {
                    //保证矩阵的行数是从第i行到第j行,然后列数不断变化,如果当前的子矩阵的和小于0了,那么肯定是加上了比较小的列,要重新开始计算
                    tempSum+=B[j][k]-B[i-1][k];
                    if(tempSum>maxSum)
                        maxSum=tempSum;
                    if(tempSum<0)
                        tempSum=0;
                }
            }
        printf("%lld\n",maxSum);
    }
    return 0;
}
posted on 2018-03-27 11:28  渡……  阅读(489)  评论(0编辑  收藏  举报