HDU 1085 多重背包转化为0-1背包问题

题目大意:

给定一堆1,2,5价值的硬币,给定三个数表示3种价值硬币的数量,任意取,找到一个最小的数无法取到

 

总价值为M = v[i]*w[i](0<=i<3)

那么在最坏情况下M个数都能取到 , M+1必然取不到

所以给M+1个背包,往里面塞东西,最后由前往后检测,找到第一个无法取满的背包的体积

 

这道题目里,每一种物品的v*w必然小于M+1,所以不出现完全背包的情况,全部采用多重背包转化为0-1背包解决问题即可

 

 1 #include <cstdio>

 2 #include <cstring>

 3 

 4 using namespace std;

 5 #define max(a,b) a>b?a:b

 6 const int N = 10000;

 7 

 8 int dp[N] , a[3] , M;

 9 int v[3] = {1 , 2 , 5};

10 void zeroPack(int w , int v)

11 {

12     for(int i = M ; i >= w ; i--)

13         dp[i] = max(dp[i-w]+v , dp[i]);

14 }

15 

16 void multiPack(int n , int w , int v)

17 {

18     int t = 1;

19     while(n > t){

20         zeroPack(t*w , t*v);

21         n -= t;

22         t <<= 1;

23     }

24     if(n > 0) zeroPack(n*w , n*v);

25 }

26 

27 int main()

28 {

29     while(1){

30         M = 0;

31         for(int i = 0 ; i<3 ; i++){

32             scanf("%d" , a+i);

33             M += a[i] * v[i];

34         }

35         if(M == 0) break;

36         //这里加一表示可能你加起来的总值都能够取到,但是多加个一,那么必然会有一个最大值取不到

37         M += 1; 

38         memset(dp , 0 ,sizeof(dp));

39         for(int i = 0 ; i<3 ; i++){

40             multiPack(a[i] , v[i] , v[i]);

41         }

42 

43         int k = 0;

44         while(dp[k] == k) k++;

45         printf("%d\n" , k);

46     }

47     return 0;

48 }

 

你可能感兴趣的:(HDU)