洛谷 P1854 花店橱窗布置

Posted 俺是小程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1854 花店橱窗布置相关的知识,希望对你有一定的参考价值。

此题原为 IOI 1999

此题的难点在于:

1.如何满足题目所述的顺序问题;

2.如何记录转移状态。

首先考虑朴素算法。着眼于问题1,不难想到枚举第一朵花的位置,然后在这个位置左边枚举第二朵花的位置......依此类推。

思考这个模型,发现其搜索树的状态存在大量重叠,且此问题满足“最优子结构”,“子问题重叠性”,“无后效性”三个dp的基础条件。

于是考虑dp。

根据朴素算法,考虑使用一个数组 f[ i ][ j ] 记录前 i 朵花占前 j 个瓶子的最大值。

于是,可以构造出核心转移:

for(int i = 2; i <= F; i++)
        for(int j = i; j <= V - F + i; j++)
            for(int k = 1; k < j; k++)
                if(f[i - 1][k] + B[i][j] > f[i][j])
                {
                    f[i][j] = f[i - 1][k] + B[i][j];
                    pre[i][j] = k;
                }

容易发现,当 f 的值得到更新,意味着从 k 处得到转移,不难想到问题二的解法:记录状态 f[ i ][ j ]的转移来源即可。

完整代码:

 1 // luogu-judger-enable-o2
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <vector>
 7 using namespace std;
 8 const int MAXF = 1e2 + 20;
 9 
10 inline int read()
11 {
12     static int x;
13     scanf("%d", &x);
14     return x;
15 }
16 
17 int f[MAXF][MAXF], pre[MAXF][MAXF];
18 int B[MAXF][MAXF];
19 int F, V;
20 
21 int main()
22 {
23     cin>>F>>V;
24     for(int i = 1; i <= F; i++)
25         for(int j = 1; j <= V; j++)
26             B[i][j] = read();
27 
28     memset(f, -0x7f, sizeof(f));
29     for(int i = 1; i <= (V - F + 1); i++)
30         f[1][i]=B[1][i], pre[1][i] = i;
31 
32     for(int i = 2; i <= F; i++)
33         for(int j = i; j <= V - F + i; j++)
34             for(int k = 1; k < j; k++)
35                 if(f[i - 1][k] + B[i][j] > f[i][j])
36                 {
37                     f[i][j] = f[i - 1][k] + B[i][j];
38                     pre[i][j] = k;
39                 }
40 
41     int ans = -0x7f7f7f7f,y;
42     for(int i = 1; i <= V; i++)
43         if(ans < f[F][i])
44              y = i, ans = f[F][i];
45 
46     int x = F;
47     std::vector<int> v;
48     for(; x >= 1; y = pre[x][y], x--)
49         v.push_back(y);
50 
51     reverse(v.begin(), v.end());
52     cout<<ans<<endl;
53     for(int i = 0; i < (int) v.size(); i++)
54         cout<<v[i]<<" ";
55     puts("");
56     return 0;
57 }

(不要吐槽奇怪的read()函数,一开始没发现有负数,写的快读,wa了好几遍。。。)

 

以上是关于洛谷 P1854 花店橱窗布置的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1854 花店橱窗布置

洛谷 P1854 花店橱窗布置

洛谷 P1854 花店橱窗布置

洛谷 P1854 花店橱窗布置

P1854 花店橱窗布置

P1854 花店橱窗布置