试题 历届试题 最大子阵(dp)

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

  其中,A的子矩阵指在A中行和列均连续的一块。
输入格式
  输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
  接下来n行,每行m个整数,表示矩阵A。
输出格式
  输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出
10
样例说明
  取最后一列,和为10。
dp经典题,枚举行与行之间列的叠加,形成一维数组,转化为一维数组最大子段和,dp[i]=max(dp[i-1]+a[i],a[i]);
代码如下
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4;
const int inf=0x3f3f3f;
int dp1[maxn];
int dp2[maxn];
int a[maxn][maxn];
int sum=-inf;
int main(){
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
                cin>>a[i][j];
    for(int i=1;i<=n;i++){
        memset(dp1,0,sizeof(dp1));///把i项行、i+i+1行的列、i+(i+1)....n的列合一起,变成一行,转为一维数组解决最大子段和
        for(int j=i;j<=n;j++){
            for(int k=1;k<=m;k++){
                dp1[k]+=a[j][k];
            }
        memset(dp2,0,sizeof(dp2));///开一个数组找一行里的最大子段和
            for(int u=1;u<=m;u++){
                dp2[u]=max(dp2[u-1]+dp1[u],dp1[u]);
                if(dp2[u]>sum)sum=dp2[u];///找到大的更新
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}
posted @ 2020-05-28 12:04  mohari  阅读(104)  评论(0编辑  收藏  举报