洛谷 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了好幾遍。。。)

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com