【题解】Luogu P1854 花店橱窗布置 dp+输出方案
首先转化题意
给定一个$n*m$的矩形,每行取一个数使得取出的数总和最大
满足
1.每行取出的数在上一行取出的数的右边
2.每一行取走的数的列数大于该行的行数
3.每一行能取的最大花瓶数小于等于$m-(n-当前行数)$
转移
设$f[i][j]$表示从第一行到第$i$行选择第$j$个的最大价值
转移方程显然 $f[i][j]=max(f[i][j],f[i-1][k]+a[i][j]) i-1<k<j $
输出方案
参考了神仙siilhouette的做法
从最后的状态每次往前推输出方案
code
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 const int maxn=5e4+10; 6 const int mod=1e9; 7 inline int read(){ 8 int f=1,x=0;char s=getchar(); 9 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 10 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 11 return f*x; 12 } 13 int n,m,a[110][110],f[110][110],ans; 14 void dfs(int x,int y){ 15 if(x>0){ 16 int k=x; 17 while(f[x][k]!=y)k++; 18 dfs(x-1,y-a[x][k]); 19 printf("%d ",k); 20 } 21 } 22 int main(){ 23 n=read();m=read(); 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=m;j++){ 26 a[i][j]=read(); 27 } 28 memset(f,128,sizeof(f)); 29 f[0][0]=0; 30 for(int i=1;i<=n;i++) 31 for(int j=1;j<=m;j++){ 32 for(int k=i-1;k<j;k++){ 33 f[i][j]=max(f[i][j],f[i-1][k]+a[i][j]); 34 } 35 } 36 for(int i=n;i<=m;i++){ 37 ans=max(ans,f[n][i]); 38 } 39 printf("%d\n",ans); 40 dfs(n,ans); 41 return 0; 42 } 43 } 44 signed main(){ 45 gengyf::main(); 46 return 0; 47 }