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 }
by Farmer