POJ 1276 Cash Machine(多重背包的二进制优化)

题目网址:http://poj.org/problem?id=1276

思路:

很明显是多重背包,把总金额看作是背包的容量。

刚开始是想把单个金额当做一个物品,用三层循环来 转换成01背包来做。T了……

后面学习了 用二进制来处理数据。

简单地介绍一下二进制优化:?(? ? ??) 

假设数量是8,则可以把它看成是1,2,4,1的组合,即这4个数的组合包括了1-8的所有取值情况。这是为什么呢?将它们转换成二进制再观察一下:

1:1

2:10

4:100

1:1

二进制都只有0,1。所以1,2,4已经能够组成1-7的所有情况,但是这样还不够 还要再加一个1 才能凑成8

或许有人会问 为什么不取到8,即1,2,4,8。注意!!所有的数加起来不可以超过数量。

我们主要是用到这些数的排列组合,取到8的话  上限就被我们扩大了,会取到原本不能取到的值。

将数量分解成之后,把number[i]*value当做一个物品,就可以转换成01背包啦~ 详情看代码!

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 int dp[100005];
 8 int a[15];
 9 vector<int>v;
10 int main(){
11     int cash;
12     int n,m,x;
13     while(scanf("%d%d",&cash,&n)!=EOF){
14         memset(dp,0, sizeof(dp));
15         v.clear();
16         dp[0]=1;
17         for (int i = 0; i < n; ++i) {
18             scanf("%d%d",&m,&x);
19             for (int j = 1; j <= m; j<<=1) {//二进制优化
20                 v.push_back(j*x);
21                 m-=j;
22             }
23             if(m>0) v.push_back(m*x);//别忘了剩余的数
24         }
25         for (int i = 0; i < v.size(); ++i) {
26             for (int j = cash; j >=v[i] ; --j) {
27                 dp[j]=max(dp[j-v[i]],dp[j]);
28             }
29         }
30         for (int i = cash; i >= 0 ; --i) {
31             if(dp[i]){
32                 printf("%d\n",i);
33                 break;
34             }
35         }
36     }
37     return 0;
38 }
时间: 2024-12-16 04:43:18

POJ 1276 Cash Machine(多重背包的二进制优化)的相关文章

poj 1276 Cash Machine (多重背包)

链接:poj 1276 题意:已知金额cash,给定几种不同面值的货币的数量及面值,求利用给定的货币可以凑成 小于等于cash的金额的最大值 分析:因为每种货币的面值及数量已知,可以将其转化为多重背包,背包的容量即为cash, 每个物品的价值及费用都为每种货币的面值. 多重背包可以转化为01背包,不过这样会超时,为了避免这样,可以转化为完全背包和二进制思想的01背包 #include<stdio.h> #include<string.h> int f[100010],v; int

POJ 1276 Cash Machine 多重背包--二进制优化

点击打开链接 Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28337   Accepted: 10113 Description A Bank plans to install a machine for cash withdrawal. The machine is able to deliver appropriate @ bills for a requested cash amount

POJ 1276 Cash Machine 背包题解

典型的多重背包的应用题解. 可以使用二进制优化,也可以使用记录当前物品的方法解,速度更加快. const int MAX_CASH = 100001; const int MAX_N = 11; int tbl[MAX_CASH], nums[MAX_N], bills[MAX_N], cash, n; int bag() { if (cash <= 0 || n <= 0) return 0; memset(tbl, 0, sizeof(int) * (cash+1)); for (int

HDU 1059(多重背包加二进制优化)

http://acm.hdu.edu.cn/showproblem.php?pid=1059 Dividing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 29901    Accepted Submission(s): 8501 Problem Description Marsha and Bill own a collection

多重背包(二进制优化)

链接:https://www.acwing.com/problem/content/5/ 有 N种物品和一个容量是 V 的背包. 第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi. 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大. 输出最大价值. 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积. 接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积.价值和数量. 输出格式 输出一个整数,表示最大

【转载】poj 1276 Cash Machine 【凑钱数的问题】【枚举思路 或者 多重背包解决】

转载地址:http://m.blog.csdn.net/blog/u010489766/9229011 题目链接:http://poj.org/problem?id=1276 题意:机器里面共有n种面额的钱币,每种各ni张,求机器吐出小于等于所要求钱币的最大值 解析1:这题大牛都用了多重背包,不过,我一同学想出了一种就这题而言特别简单有效的方 法.(话说我就认为这题本来就不需要用到背包的,因为n的范围只到10,太小了).方法就是对钱进行遍历,看这些钱一共能组成多少面额的钱,然后从 cash向下枚

poj 1276 Cash Machine(多重背包)

Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26954   Accepted: 9533 题目大意:有各种不同面值的货币,每种面值的货币有不同的数量,请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额. 多重背包转0 1背包 对于第 i 种货币可能的状态为w[ i ]到cash 状态方程 dp[j]=dp[ j-c[i] ]+w[i]   (c[ i ] 表示"体积"

POJ1276:Cash Machine(多重背包)

题目:http://poj.org/problem?id=1276 多重背包模板题,没什么好说的,但是必须利用二进制的思想来求,否则会超时,二进制的思想在之前的博客了有介绍,在这里就不多说了. #include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <math.h> using namespace std; int V,n,w

POJ 1276 Cash Machine 【DP】

多重背包的模型,但一开始直接将N个物品一个一个拆,拆成01背包竟然T了!!好吧OI过后多久没看过背包问题了,翻出背包九讲看下才发现还有二进制优化一说........就是将n个物品拆成系数:1,2,4,8....*物品价值和空间的物品,在这题中只要乘上money[i]就行了,从二进制考虑发现,这样可以组成0~n中所有的数 #include <iostream> #include <cstdio> #include<string.h> using namespace std