题解
dp题呐。
状态:\(dp[i][j]\)表示前\(i\)种花使用\(i\)个花瓶得到的最大美观值。
初始值:\(dp[i][j]=-inf,dp[0][k]=0\quad (1\le i\le n,1\le j\le m,0\le k\le m)\)
答案可能是负数,初始值需要为极小值。
转移:\(dp[i][j]=min(dp[i-1][k]+v[i][j]))\quad(1\le i\le n,i\le j\le m,i-1\le k<j)\)
答案:\(ans=max(dp[n][i])\quad (n\le i\le m)\)
此外,此题需要输出方案,并且需要按照字典序输出,因此,题解作者写了长长的代码为了比较答案相同方案字典序(智商\(--\),快乐\(++\))。但是!\(i\)最小的\(dp[k][i]\)字典序也一定最小。设\(j\)满足\(j>i,dp[k][j]=dp[k][i]\),若\(v[k][j]\le v[k][i]\),则\(dp[k-1][j]\ge dp[k-1][i]\),因此\(i\le j\);若\(v[k][j]>v[k][i]\),则\(dp[k-1][j]<dp[k-1][i]\),但是\(dp[k][j]\)一定可以取到\(dp[k-1][i]\),因此\(dp[k][j]>dp[k][i]\),矛盾。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int v[N][N],dp[N][N],pre[N][N],qwq[N];
int main()
{
int n,m,ans=0,pos;
memset(dp,-0x3f,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%d",&v[i][j]);
for(int i=0;i<=m;i++) dp[0][i]=0;
for(int i=1;i<=n;i++)
for(int j=i;j<=m;j++)
for(int k=i-1;k<j;k++)
if(dp[i][j]<dp[i-1][k]+v[i][j]) dp[i][j]=dp[i-1][k]+v[i][j],pre[i][j]=k;
for(int i=1;i<=m;i++)
if(dp[n][i]>ans) ans=dp[n][i],pos=i;
printf("%d\n",ans);
for(int i=n;i>=1;i--) qwq[i]=pos,pos=pre[i][pos];
for(int i=1;i<=n;i++) printf("%d ",qwq[i]);
return 0;
}