nyoj 104——最大和——————【子矩阵最大和】

最大和

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
 
描述

给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。 
例子:
0 -2 -7 0 
9 2 -6 2 
-4 1 -4 1 
-1 8 0 -2 
其最大子矩阵为:

9 2 
-4 1 
-1 8 
其元素总和为15。 

 
输入
第一行输入一个整数n(0<n<=100),表示有n组测试数据;
每组测试数据:
第一行有两个的整数r,c(0<r,c<=100),r、c分别代表矩阵的行和列;
随后有r行,每行有c个整数;
输出
输出矩阵的最大子矩阵的元素之和。
样例输入
1
4 4
0 -2 -7 0 
9 2 -6 2 
-4 1 -4 1 
-1 8 0 -2 
样例输出
15


解题思路:这是一个很基本的模型。求矩阵的最大子矩阵和。这个在最大字段和的基础上,通过暴力枚举x*m大小的子矩阵(将子矩阵化成一行的形式,即求列的前缀和),再套用求子段和的方法,最后得到的就是结果。


#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
const int INF=1e9;
int a[maxn][maxn];
int pref_sum[maxn];
int n,m;
int MaxSubSegSum(){ //最大子段和
    int ret=-INF,tmp=0;
    for(int i=0;i<m;i++){
        if(tmp<0){
            tmp=pref_sum[i];
        }else{
            tmp+=pref_sum[i];
        }
        if(tmp>ret){
            ret=tmp;
        }
    }
    return ret;
}
int main(){
    int t,i,j,k;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                scanf("%d",&a[i][j]);
            }
        }
        int ans=-INF;
        for(i=0;i<n;i++){   //枚举子矩阵第一行位置
            memset(pref_sum,0,sizeof(pref_sum));
            for(j=i;j<n;j++){   //枚举子矩阵行数
                for(k=0;k<m;k++){
                    pref_sum[k]+=a[j][k];
                }
                int tmp=MaxSubSegSum();
                if(tmp>ans)
                    ans=tmp;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/chengsheng/p/4503759.html