poj 1276 Cash Machine

题意:

一个银行有若干不同面值的货币,每个面值有不同的数量,求银行可以凑出最大的小于等于给定金额的钱的数值。

思路:

组合背包裸题,把数量以二进制拆分,就可以凑出从1到k的所有数,时间复杂度降到log(k)。之后再用0,1背包解决。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 
 7 const int M = 100005;
 8 
 9 int f[M];
10 
11 vector<int> num,val;
12 
13 int main()
14 {
15     int cash,n;
16     
17     while (scanf("%d%d",&cash,&n) != EOF)
18     {
19         memset(f,0,sizeof(f));
20         
21         num.clear();
22         val.clear();
23         
24         for (int i = 0;i < n;i++)
25         {
26             int t,d;
27             
28             scanf("%d%d",&t,&d);
29             
30             int cnt = 0;
31             
32             while (1)
33             {
34                 int tmp = (1 << cnt);
35                 
36                 if (t <= tmp)
37                 {
38                     num.push_back(t);
39                     val.push_back(t * d);
40                     break;
41                 }
42                 
43                 num.push_back(tmp);
44                 val.push_back(tmp * d);
45                 
46                 t -= tmp;
47                 
48                 cnt++;
49             }
50         }
51         
52         int ans = 0;
53         
54         for (int i = 0;i < val.size();i++)
55         {
56             for (int j = cash;j >= val[i];j--)
57             {
58                 f[j] = max(f[j],f[j-val[i]] + val[i]);
59                 ans = max(ans,f[j]);
60             }
61         }
62         
63         printf("%d
",ans);
64     }
65     
66     return 0;
67 }
原文地址:https://www.cnblogs.com/kickit/p/8808768.html