背包专题C - The trouble of Xiaoqian hdu3591混合背包:多重背包+完全背包
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了背包专题C - The trouble of Xiaoqian hdu3591混合背包:多重背包+完全背包相关的知识,希望对你有一定的参考价值。
And now , Xiaoqian wants to buy T (1 ≤ T ≤ 10,000) cents of supplies. The currency system has N (1 ≤ N ≤ 100) different coins, with values V1, V2, ..., VN (1 ≤ Vi ≤ 120). Xiaoqian is carrying C1 coins of value V1, C2 coins of value V2, ...., and CN coins of value VN (0 ≤ Ci ≤ 10,000). The shopkeeper has an unlimited supply of all the coins, and always makes change in the most efficient manner .But Xiaoqian is a low-pitched girl , she wouldn’t like giving out more than 20000 once.
InputThere are several test cases in the input.
Line 1: Two space-separated integers: N and T.
Line 2: N space-separated integers, respectively V1, V2, ..., VN coins (V1, ...VN)
Line 3: N space-separated integers, respectively C1, C2, ..., CN
The end of the input is a double 0.
OutputOutput one line for each test case like this ”Case X: Y” : X presents the Xth test case and Y presents the minimum number of coins . If it is impossible to pay and receive exact change, output -1.Sample Input
3 70 5 25 50 5 2 1 0 0
Sample Output
Case 1: 3
题意:顾客需要v价值的物品,问,付款的硬币数最小是多少,给定n种硬币的价值和数量,当顾客付款超过v时,商家需要找钱给顾客,商家找的钱也计入硬币总数。题目中说明了商家可以找回任意价值的钱币,数量无限,需要注意题目提醒,顾客一次性付钱不超过20000.
思路:这道题如果按照平常把v价值的物品作为上限(也就是背包容量),会发现无法处理付款超过v时的情况,根据题目提示,顾客一次性付款不超过20000,我们可以将20000作为背包容量,在此背包容量下,可以计算v~20000任意价值的最小付款硬币量,因为不一定超过了给定的v,钱币数量就最大或者最小,我们需要在最后遍历比较得出最小值,ans = min(ans,dp1[i]+dp2[i-v]),dp1存的是顾客付款为v时的最小硬币数,dp2存的是商家找钱为i-v时的最小硬币数。注意dp1[0]和dp2[0]我们需要初始化为0,因为一开始硬币数为0。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define inf 0x3f3f3f3f #define N 20010 int dp1[N],dp2[N],value[110],num[110]; int n,v,ans; void CompletePack(int value) { int i; for(i = value; i < N ; i ++) dp1[i] = min(dp1[i],dp1[i-value]+1); return; } void ZeroOnePack(int value,int num) { int i; for(i = N-1; i >= value; i --) dp1[i] = min(dp1[i],dp1[i-value]+num); return; } int main() { int i,j,k,x,t=0; while(scanf("%d%d",&n,&v),(n+v)) { for(i = 1; i <= n; i ++) scanf("%d",&value[i]);//读入硬币价值 for(i = 1; i <= n; i ++) scanf("%d",&num[i]);//读入硬币数量 for(i = 0; i < N; i ++) { dp1[i] = inf;//初始化,因为我们所求的数量需要最小 dp2[i] = inf; } dp1[0] = dp2[0] = 0;//一开始初始化为0,数量为0 for(i = 1; i <= n; i ++)//对顾客来说,是一个多重背包的问题 { if(num[i]*value[i] > v) CompletePack(value[i]); else { k = 1; while(num[i]>0) { x = min(k,num[i]); ZeroOnePack(x*value[i],x); num[i] -= x; k*= 2; } } } for(i = 1; i <= n; i ++)//由题可知,商家的硬币数量是无限的,所以是完全背包 for(j = value[i]; j < N;j ++) dp2[j] = min(dp2[j],dp2[j-value[i]]+1); ans = inf;//我们需要最小值,所以先初始化为一个极大值 for(i = v; i < N; i ++) ans = min(ans,dp1[i]+dp2[i-v]);//顾客付款为i时,店家需要找钱i-v。 printf("Case %d: ",++t); if(ans == inf) printf("-1\n"); else printf("%d\n",ans); } return 0; }
以上是关于背包专题C - The trouble of Xiaoqian hdu3591混合背包:多重背包+完全背包的主要内容,如果未能解决你的问题,请参考以下文章
hdu 3591 The trouble of Xiaoqian
C. Coin Troubles 有依赖的背包 + 完全背包变形
Level of Qustion:Record the difficult level of Problem For future review