POJ-1276 Cash Machine---多重背包

题目链接:

https://cn.vjudge.net/problem/POJ-1276

题目大意:

有各种不同面值的货币,每种面值的货币有不同的数量,请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额。

解题思路:

多重背包+二进制优化

dp[i]为真表示可以凑出i元

注意dp[0] = true

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 using namespace std;
 6 const int maxn = 1e6 + 10;
 7 bool dp[maxn];
 8 int n, m;
 9 void Zeroone(int cost)
10 {
11     for(int i = m; i >= cost; i--)
12         if(dp[i - cost])dp[i] = 1;
13 }
14 void Compete(int cost)
15 {
16     for(int i = cost; i <= m; i++)
17         if(dp[i - cost])dp[i] = 1;
18 }
19 void solve(int cost, int amount)
20 {
21     if(cost * amount >= m)
22         Compete(cost);
23     else
24     {
25         int k = 1;//二进制优化
26         while(k <= amount)
27         {
28             Zeroone(k * cost);
29             amount -= k;
30             k *= 2;
31         }
32         Zeroone(amount * cost);
33     }
34 }
35 int main()
36 {
37     while(scanf("%d%d", &m, &n) != EOF)
38     {
39         int amount, cost;
40         memset(dp, 0, sizeof(dp));
41         dp[0] = 1;
42         while(n--)
43         {
44             scanf("%d%d", &amount, &cost);
45             solve(cost, amount);
46         }
47         for(int i = m; i >= 0; i--)
48             if(dp[i])
49         {
50             printf("%d\n", i);
51             break;
52         }
53     }
54     return 0;
55 }

 

posted @ 2018-05-08 18:44  _努力努力再努力x  阅读(166)  评论(0编辑  收藏  举报