洛谷P2736 “破锣摇滚”乐队 Raucous Rockers

小破题!

有剧毒。

三维的DP方程,可以优化到二维,还有奇淫技巧用一维。

我当然是选择三维啦!

f[i][j][k]表示前i首歌前j张CD的k空间,最多能放下的歌数。

决策:

1.放弃这首歌,此时 f[i][j][k] = f[i - 1][j][k]

2.放到这张CD里(如果放得下),此时 f[i][j][k] = f[i - 1][j][k - cost[i]]

3.放到上一张CD里(如果j > 1),此时 f[i][j][k] = f[i - 1][j - 1][t - cost[i]]

然后按照 i j k 的顺序循环,答案就是 max(f[n][j][k])

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using std::max;
 5 const int N = 30;
 6 
 7 int cost[N], f[N][N][N];
 8 
 9 int main() {
10     int n = 0, t, m, p, x;
11     //memset(f, 0xcf, sizeof(f));
12     scanf("%d%d%d", &p, &t, &m);
13     for(int i = 1; i <= p; i++) {
14         scanf("%d", &x);
15         if(x <= t) {
16             cost[++n] = x;
17         }
18     }
19 
20     f[0][1][0] = 0;
21     for(int i = 1; i <= n; i++) {
22         for(int j = 1; j <= m; j++) {
23             for(int k = 0; k <= t; k++) {
24                 if(cost[i] <= k) {
25                     f[i][j][k] = max(f[i - 1][j][k], f[i - 1][j][k - cost[i]] + 1);
26                 }
27                 else if(j > 1) {
28                     f[i][j][k] = max(f[i - 1][j - 1][t - cost[i]] + 1, f[i - 1][j][k]);
29                 }
30                 else {
31                     f[i][j][k] = f[i - 1][j][k];
32                 }
33             }
34         }
35     }
36 
37     int ans = -1;
38     for(int i = 1; i <= m; i++) {
39         for(int j = 1; j <= t; j++) {
40             ans = max(ans, f[n][i][j]);
41         }
42     }
43     printf("%d", ans);
44     return 0;
45 }
AC代码

 

posted @ 2018-06-08 10:47  garage  阅读(105)  评论(0编辑  收藏  举报