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 }