[CF808E] Selling Souvenirs(dp,背包)

题目链接:http://codeforces.com/contest/808/problem/E

题意:就是01背包,但是物品的重量只有1 2 3三种,背包容量会超大。

三种重量按照价值从大到小排序,dp数组记录当前1、2重量的使用状态以及当前价值。更新完dp后,维护重量为3的物品的前缀和,再扫一遍,看看能不能用重量为3的前k个替换,更新最大值就行了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 typedef struct Node {
 6     int a, b;
 7     LL v;
 8 }Node;
 9 
10 const int maxn = 300200;
11 LL n, w;
12 LL bag[4][maxn];
13 LL sum[maxn];
14 Node dp[maxn];
15 int a, b, c;
16 
17 int main() {
18     freopen("in", "r", stdin);
19     int x;
20     LL y;
21     while(~scanf("%I64d%I64d",&n,&w)) {
22         a = b = c = 0;
23         memset(sum, 0, sizeof(sum));
24         for(int i = 0; i < n; i++) {
25             scanf("%d%I64d",&x,&y);
26             if(x == 1) bag[1][++a] = y;
27             if(x == 2) bag[2][++b] = y;
28             if(x == 3) bag[3][++c] = y;
29         }
30         sort(bag[1]+1, bag[1]+a+1, greater<LL>());
31         sort(bag[2]+1, bag[2]+b+1, greater<LL>());
32         sort(bag[3]+1, bag[3]+c+1, greater<LL>());
33         for(int i = 1; i <= c; i++) sum[i] = sum[i-1] + bag[3][i];
34         dp[0] = Node{0,0,0};
35         for(int i = 1; i <= w; i++) {
36             dp[i] = dp[i-1];
37             if(dp[i-1].a < a && dp[i-1].v + bag[1][dp[i-1].a+1] > dp[i].v) {
38                 dp[i] = dp[i-1];
39                 dp[i].v += bag[1][dp[i-1].a+1];
40                 dp[i].a++;
41             }
42             if(i >= 2 && dp[i-2].b < b && dp[i-2].v + bag[2][dp[i-2].b+1] > dp[i].v) {
43                 dp[i] = dp[i-2];
44                 dp[i].v += bag[2][dp[i-2].b+1];
45                 dp[i].b++;
46             }
47             // if(i >= 2 && dp[i-2].a + 1 < a && dp[i-1].v + bag[1][dp[i-1].a+1] + bag[1][dp[i-1].a+2] > dp[i].v) {
48             //     dp[i] = dp[i-2];
49             //     dp[i].v += bag[1][dp[i-1].a+1] + bag[1][dp[i-1].a+2];
50             //     dp[i].a += 2;
51             // }
52             // if(i >= 3 && dp[i-3].c < c && dp[i-3].v + bag[3][dp[i-3].c+1] > dp[i].v) {
53             //     dp[i] = dp[i-3];
54             //     dp[i].v += bag[3][dp[i-3].c+1];
55             //     dp[i].c++;
56             // }
57             // if(i >= 3 && dp[i-3].a < a && dp[i-3].b < b && dp[i-3].v + bag[1][dp[i-3].a+1] + bag[2][dp[i-3].b+1] > dp[i].v) {
58             //     dp[i] = dp[i-3];
59             //     dp[i].v += bag[1][dp[i-3].a+1] + bag[2][dp[i-3].b+1];
60             //     dp[i].a++; dp[i].b++;
61             // }
62             // if(i >= 3 && dp[i-3].a + 2 < a && dp[i-3].v + bag[1][dp[i-3].a+1] + bag[1][dp[i-3].a+2] + bag[1][dp[i-3].a+3] > dp[i].v) {
63             //     dp[i] = dp[i-3];
64             //     dp[i].v += bag[1][dp[i-3].a+1] + bag[1][dp[i-3].a+2] + bag[1][dp[i-3].a+3];
65             //     dp[i].a += 3;
66             // }
67         }
68         LL ret = dp[w].v;
69         for(int i = 1; i <= c; i++) {
70             if(w >= i * 3) ret = max(ret, sum[i] + dp[w-3*i].v);
71         }
72         printf("%I64d\n", ret);
73     }
74     return 0;
75 }

 

posted @ 2017-05-16 15:48  Kirai  阅读(314)  评论(0编辑  收藏  举报