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 }

 

你可能感兴趣的:(write)