洛谷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 }