题解
虽然是
12
年前的题但是并不好做。
注意到
m=1
或
m=2
。
当
m=1
时,
g[i][k]
表示前
i
个数选了
当
转移可以预处理最大连续子段和。
题外话
4 2 8
4 2
3 -2
-1 -5
5 4
这组数据会把网上的大部分题解卡掉
代码
//动态规划
#include <cstdio>
#include <algorithm>
#define maxn 110
#define inf 0x3f3f3f3f
using namespace std;
int f[maxn][maxn][15], g[maxn][15], a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], N, K,
M, w[maxn][maxn];
int main()
{
int i, j, k, ans=-inf, t;
scanf("%d%d%d",&N,&M,&K);
for(i=1;i<=N;i++)for(j=1;j<=M;j++)scanf("%d",&w[j][i]);
for(i=1;i<=N;i++)for(j=i;j<=N;j++)a[i][j]=max(a[i][j-1],0)+w[1][j];
for(i=1;i<=N;i++)for(j=i;j<=N;j++)b[i][j]=max(b[i][j-1],0)+w[2][j];
for(i=1;i<=N;i++)for(j=i;j<=N;j++)c[i][j]=max(0,c[i][j-1])+w[1][j]+w[2][j];
if(M==1)
{
for(i=1;i<=K;i++)g[0][i]=-inf;
for(i=1;i<=N;i++)
for(k=1;k<=K;k++)
{
g[i][k]=-inf;
for(j=0;j<i;j++)g[i][k]=max(g[i][k],g[j][k-1]+a[j+1][i]);
}
for(i=1;i<=N;i++)ans=max(ans,g[i][K]);
}
if(M==2)
{
for(i=0;i<=N;i++)for(j=1;j<=K;j++)f[i][0][j]=f[0][i][j]=-inf;
for(i=0;i<=N;i++)
for(j=0;j<=N;j++)
for(k=1;k<=K;k++)
{
if(i)f[i][j][k]=max(f[i][j][k],f[i-1][j][k]);
if(j)f[i][j][k]=max(f[i][j][k],f[i][j-1][k]);
if(i==j)
for(t=0;t<i;t++)
f[i][i][k]=max(f[i][i][k],f[t][t][k-1]+c[t+1][i]);
for(t=0;t<i;t++)f[i][j][k]=max(f[i][j][k],f[t][j][k-1]+a[t+1][i]);
for(t=0;t<j;t++)f[i][j][k]=max(f[i][j][k],f[i][t][k-1]+b[t+1][j]);
for(t=0;t<min(i,j);t++)f[i][j][k]=max(f[i][j][k],f[t][t][k-1]);
ans=max(ans,f[i][j][k]);
}
ans=f[N][N][K];
}
printf("%d\n",ans);
return 0;
}