试题 历届试题 最大子阵(dp)
问题描述
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
其中,A的子矩阵指在A中行和列均连续的一块。
其中,A的子矩阵指在A中行和列均连续的一块。
输入格式
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
接下来n行,每行m个整数,表示矩阵A。
输出格式
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
-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;
}