【题解】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
",ans);
40     dfs(n,ans);
41     return 0;
42 }
43 }
44 signed main(){
45   gengyf::main();
46   return 0;
47 }
View Code
原文地址:https://www.cnblogs.com/gengyf/p/11677958.html