hdu2844 Coins

http://acm.hdu.edu.cn/showproblem.php?pid=2844

DP,部分背包

耗费:钱币的面值,价值:全为1,数量:每种钱币的数量,

求恰好装满的dp值,初始化dp[0]=0,dp[1~m] = “负无穷”,

最后遍历dp[1~m],如果能恰好装满(dp值为正)就算一种,统计一共有多少种

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 #define N 100100
 5 
 6 int n, m;
 7 int dp[N], w[123], num[123];
 8 const int minint = -1234567;
 9 
10 void pack01(int wi, int vi)
11 {
12     int j;
13     for(j=m; j>=wi; j--)
14     {
15         if(dp[j-wi]+vi > dp[j])
16         {
17             dp[j] = dp[j-wi]+vi;
18         }
19     }
20 }
21 
22 void pack(int wi, int vi)
23 {
24     int j;
25     for(j=wi; j<=m; j++)
26     {
27         if(dp[j-wi]+vi > dp[j])
28         {
29             dp[j] = dp[j-wi]+vi;
30         }
31     }
32 }
33 
34 int main()
35 {
36     int i, k, result;
37     while(scanf("%d%d", &n, &m), n||m)
38     {
39         for(i=1; i<=n && scanf("%d", w+i); i++);
40         for(i=1; i<=n && scanf("%d", num+i); i++);
41         for(i=1; i<=m; i++)
42         {
43             dp[i] = minint;
44         }
45         dp[0] = 0;
46         for(i=1; i<=n; i++)
47         {
48             if(w[i]*num[i] >= m)
49             {
50                 pack(w[i], 1);
51                 continue;
52             }
53             for(k=1; k<num[i]; k<<=1)
54             {
55                 pack01(w[i]*k, 1);
56                 num[i] -= k;
57             }
58             pack01(w[i]*num[i], 1);
59         }
60         result = 0;
61         for(i=1; i<=m; i++)
62         {
63             if(dp[i] > 0)
64             {
65                 result ++;
66             }
67         }
68         printf("%d\n", result);
69     }
70     return 0;
71 }

 

posted @ 2013-01-29 23:09  Yuan1991  阅读(149)  评论(0编辑  收藏  举报