题目链接: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 ", ret); 73 } 74 return 0; 75 }