hdu 3732 Ahui Writes Word(多重背包)

因为 0 ≤ Vi , Ci ≤ 10 , 范围很小,故可以转化为多重背包+二进制优化来解决。

分解为系数为1,2,4,8...Mi-2^k+1的物品再做01背包。

View Code
 1 /*
 2 Author:Zhaofa Fang
 3 Lang:C++
 4 */
 5 #include <cstdio>
 6 #include <cstdlib>
 7 #include <sstream>
 8 #include <iostream>
 9 #include <cmath>
10 #include <cstring>
11 #include <algorithm>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 #include <queue>
16 #include <stack>
17 #include <map>
18 #include <set>
19 using namespace std;
20 
21 typedef long long ll;
22 #define DEBUG(x) cout<< #x << ':' << x << endl
23 #define REP(i,n) for(int i=0;i < (n);i++)
24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)
25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)
26 #define PII pair<int,int>
27 #define PB push_back
28 #define MP make_pair
29 #define ft first
30 #define sd second
31 #define lowbit(x) (x&(-x))
32 #define INF (1<<30)
33 
34 int dp[10005];
35 int word[13][13];
36 int main()
37 {
38     //freopen("in","r",stdin);
39     //freopen("out","w",stdout);
40     int N,C;
41     while(~scanf("%d%d",&N,&C))
42     {
43         char str[15];
44 
45         memset(dp,0,sizeof(dp));
46         memset(word,0,sizeof(word));
47         REP(i,N)
48         {
49             int c,v;
50             scanf("%s%d%d",str,&v,&c);
51             word[v][c] ++;
52         }
53         REP(i,11) REP(j,11)
54         {
55             if(!word[i][j])continue;
56             int k = 1,tmp = word[i][j],tot=0;
57             while(tot<word[i][j])
58             {
59                 FORD(v,C,k*j)
60                 {
61                     dp[v] = max(dp[v],dp[v-k*j]+k*i);
62                 }
63                 tot += k; k<<=1;
64                 if(tot+k > word[i][j])k = word[i][j] - tot;
65             }
66         }
67         printf("%d\n",dp[C]);
68     }
69     return 0;
70 }

 

posted @ 2013-02-19 17:36  發_  阅读(169)  评论(0编辑  收藏  举报