题目链接
最大子矩阵
dp方法。题目说明了列数最大为2,首先考虑只有1列的情况dp[n][k]表示前n个数的最大k个子数组和,那么使用sum表示前缀和就有dp[i][k] = dp[j][k-1]+sum[i]-sum[j];
那么考虑这道题,可以理解为从第一列选择i行,从第二列选择j行,使得子数组个数和为k,且和最大,对于每一列都可以使用1列的dp来求解,sum此时就是一个二维数组,第二个元素表示哪一列。
特别的,当i=j时那么需要考虑两列合并的和比单独一列大的情况。
具体代码如下
#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;
int a[110][110];
int dp[110][110][20];
int s[110][3];
int main()
{
int n,m,t;
cin>>n>>m>>t;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
s[i][j]=s[i-1][j]+a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=t;k++){
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k]);
//第一列缩减到p
for(int p=0;p<i;p++)
dp[i][j][k]=max(dp[i][j][k],dp[p][j][k-1]+s[i][1]-s[p][1]);
//第二列缩减到p
for(int p=0;p<j;p++)
dp[i][j][k]=max(dp[i][j][k],dp[i][p][k-1]+s[j][2]-s[p][2]);
//两列合并
if(i==j){
for(int p=0;p<i;p++)
dp[i][j][k]=max(dp[i][j][k],dp[p][p][k-1]+s[i][1]+s[j][2]-s[p][1]-s[p][2]);
}
}
}
}
cout<<dp[n][n][t];
return 0;
}