poj1276 Cash Machine-多重背包
来源:互联网 发布:mac系统 high sierra 编辑:程序博客网 时间:2024/05/22 06:48
Cash Machine
Description
A Bank plans to install a machine for cash withdrawal. The machine is able to deliver appropriate @ bills for a requested cash amount. The machine uses exactly N distinct bill denominations, say Dk, k=1,N, and for each denomination Dk the machine has a supply of nk bills. For example,
N=3, n1=10, D1=100, n2=4, D2=50, n3=5, D3=10
means the machine has a supply of 10 bills of @100 each, 4 bills of @50 each, and 5 bills of @10 each.
Call cash the requested amount of cash the machine should deliver and write a program that computes the maximum amount of cash less than or equal to cash that can be effectively delivered according to the available bill supply of the machine.
Notes:
@ is the symbol of the currency delivered by the machine. For instance, @ may stand for dollar, euro, pound etc.
N=3, n1=10, D1=100, n2=4, D2=50, n3=5, D3=10
means the machine has a supply of 10 bills of @100 each, 4 bills of @50 each, and 5 bills of @10 each.
Call cash the requested amount of cash the machine should deliver and write a program that computes the maximum amount of cash less than or equal to cash that can be effectively delivered according to the available bill supply of the machine.
Notes:
@ is the symbol of the currency delivered by the machine. For instance, @ may stand for dollar, euro, pound etc.
Input
The program input is from standard input. Each data set in the input stands for a particular transaction and has the format:
cash N n1 D1 n2 D2 ... nN DN
where 0 <= cash <= 100000 is the amount of cash requested, 0 <=N <= 10 is the number of bill denominations and 0 <= nk <= 1000 is the number of available bills for the Dk denomination, 1 <= Dk <= 1000, k=1,N. White spaces can occur freely between the numbers in the input. The input data are correct.
cash N n1 D1 n2 D2 ... nN DN
where 0 <= cash <= 100000 is the amount of cash requested, 0 <=N <= 10 is the number of bill denominations and 0 <= nk <= 1000 is the number of available bills for the Dk denomination, 1 <= Dk <= 1000, k=1,N. White spaces can occur freely between the numbers in the input. The input data are correct.
Output
For each set of data the program prints the result to the standard output on a separate line as shown in the examples below.
Sample Input
735 3 4 125 6 5 3 350633 4 500 30 6 100 1 5 0 1735 00 3 10 100 10 50 10 10
Sample Output
73563000
Hint
The first data set designates a transaction where the amount of cash requested is @735. The machine contains 3 bill denominations: 4 bills of @125, 6 bills of @5, and 3 bills of @350. The machine can deliver the exact amount of requested cash.
In the second case the bill supply of the machine does not fit the exact amount of cash requested. The maximum cash that can be delivered is @630. Notice that there can be several possibilities to combine the bills in the machine for matching the delivered cash.
In the third case the machine is empty and no cash is delivered. In the fourth case the amount of cash requested is @0 and, therefore, the machine delivers no cash.
In the second case the bill supply of the machine does not fit the exact amount of cash requested. The maximum cash that can be delivered is @630. Notice that there can be several possibilities to combine the bills in the machine for matching the delivered cash.
In the third case the machine is empty and no cash is delivered. In the fourth case the amount of cash requested is @0 and, therefore, the machine delivers no cash.
题目大意
给你一个总钱数cash,N种货币,每种有n个,问这些货币最多能拼成多少钱,使之最接近cash。
解题思路
思路一、多重背包的模板题,推荐看背包九讲
本来用的基本方法,结果超时了,果然还是得用优化的。心塞
其实就是转化为价值和消耗相等的01背包,把每种物品分解为多种物品,然后使用01背包求解。基本思路是枚举k ,让k*原参数成为一个新的物品,这样1个物品就变成了n个物品。
事实上这种办法容易超时,需要优化
考虑这样一个问题,真的需要枚举每个k吗?
例如某种物品数量为13,那么可以分解为1.2.3.4.5……13,这样每个数都能达到,但是拿取1和3是不是相当于拿取4呢?同样 拿取6 7是不是直接相当于拿取13呢
于是我们希望优化系数,想到二进制的思想,2进制可以表示任意数,如果我们把13分解为 1 2 4 6,这样会发现,1~13中每一个数都能用其中任意一个或多个相加来表示。
至于k,我们规定 n-2^k+1>0,最后一个 系数 是 总数 - 满足条件的所有k。
思路二、枚举面值
还有一种思想是枚举面值,如果面值为j可以达到,那么面值为 j+k*cost[i] (k属于n[i])也能达到.解题过程中就记录更新最大的面值。
代码
思路一
#include <iostream>#include <cstdio>#include <cstring>using namespace std;int cash,n,i,j,k;int dp[100010],num[11000],cost[11000];void zeroonepack(int cost){ int i; for(i=cash;i>=cost;--i) { dp[i]= max(dp[i-cost]+cost,dp[i]); }}void complete_pack(int cost){ int i; for(i=cost;i<=cash;++i) dp[i]=max(dp[i],dp[i-cost]+cost);}void multiple_pack(int n,int cost){ if(n*cost>=cash)//相当于这个物品有无限件,完全背包 complete_pack(cost); else { int k=1; while(k<n) { zeroonepack(cost*k); n-=k; k*=2; } zeroonepack(cost*n); }}int main(){ while(scanf("%d",&cash)!=EOF) { scanf("%d",&n); for(i=0;i<n;++i) scanf("%d%d",&num[i],&cost[i]); if(!cash || !n) printf("0\n"); else { memset(dp,0,sizeof(dp)); for(i=0;i<n;++i) { multiple_pack(num[i],cost[i]); } printf("%d\n",dp[cash]); } } return 0;}
思路二
#include<cstdio>#include <cstring>using namespace std;int cash,n,i,j,k,maxn=0;int dp[100010],num[11000],cost[11000];int main(){ while(scanf("%d",&cash)!=EOF) { scanf("%d",&n); for(i=0;i<n;++i) scanf("%d%d",&num[i],&cost[i]); if(!cash || !n) printf("0\n"); else { maxn=0; memset(dp,0,sizeof(dp)); dp[0]=1; for(i=0;i<n;++i) { for(j=maxn;j>=0;j--) { if(dp[j]) { for(k=1;k<=num[i];++k) { int t=j+k*cost[i]; if(t<=cash) { dp[t]=1; if(t>maxn) maxn=t; } } } } } printf("%d\n",maxn); } } return 0;}
1 0
- poj1276(Cash Machine + 多重背包)
- POJ1276:Cash Machine(多重背包)
- POJ1276:Cash Machine(多重背包)
- poj1276 Cash Machine-多重背包
- POJ1276:Cash Machine(多重背包)
- POJ1276-Cash Machine(多重背包)
- POJ1276 Cash Machine(多重背包问题)
- poj1276--Cash Machine(多重背包判可达)
- POJ1276 Cash Machine(多重背包~~)
- poj1276 Cash Machine(多重背包)
- POJ1276 Cash Machine(多重背包)
- poj1276 Cash Machine(多重背包)
- [背包]poj1276 Cash Machine
- 背包(2)poj1276 Cash Machine(多重背包)
- ZOJ1366 POJ1276 Cash Machine 经典多重背包问题
- poj1276——Cash Machine(多重背包)
- pOJ1276 Cash Machine(背包)
- Cash Machine--多重背包
- HDU 2087 剪花布条
- 不用selector实现button的简单点击效果
- NPM常用命令
- codeforces 710E
- hdu 2282 Chocolate【KM匹配+建图】
- poj1276 Cash Machine-多重背包
- 陕西省集训之树状数组
- jsp的window对象的属性和方法大全
- java 两种日志的使用方式
- POJ 3414Pots
- android Spinner控件详解
- C语言求矩阵的行列式、伴随矩阵、逆矩阵
- listview滑动到底部弹出按钮-button占用了listview的显示位置(尽力理解尽力解决)
- yolo5类检测成功