储钱罐
【题目描述】
今年的ACM比赛在xxx国举行,为了比赛的顺利进行,必须提前预算好需要的费用,以及费用的来源。费用的主要来源是只进不出的金钱。其实原理很简单,每当ACM成员有任何一点小钱,他们就会把这些钱全部投进储钱罐。你知道钱投进储钱罐后是无法再取出来的,除非你打碎储钱罐,而这是不允许的。经过一段足够长时间的积累,储钱罐中应该有足够的金钱来支付ACM比赛需要的一切费用。
储钱罐不允许打碎,我们也不能确定里面有多少钱,钱是否够用。不过,我们知道储钱罐以及每种硬币的重量,于是我们可以试着猜测里面有多少钱。为了保险起见,在已知重量的前提下,我们需要算出储钱罐中最少有多少钱(每种硬币可以使用多次,)。你能帮忙预算一下吗?
【输入】
第一行,两个正整数E和F,分别为空储钱罐的重量和装满硬币的储钱罐的重量(重量的单位是克,并且不会超过10公斤,即:1 <= E <= F <= 10000)。
第二行,有一个正整数n(1 <= N <= 500),为硬币的种类。
后面紧跟n行,每行为一种硬币类型,包含两个正整数p和w ,p为硬币的价值,w为硬币的重量,单位为克。(1 < = P < = 50000,1 < = W < = 10000)。
【输出】
输出只有一行,如果能求出符合要求的储蓄罐的最低金额,则输出该金额,否则输出“This is impossible.”。
【输入样例1】
10 110
2
1 1
30 50
【输出样例1】
60
【输入样例2】
10 110
2
1 1
50 30
【输出样例2】
100
【输入样例3】
1 6
2
10 3
20 4
【输出样例3】
This is impossible.
一句话题意:恰好装满容量为ff-e的背包,需要的最少硬币金额是多少?
分析:完全背包问题+恰好装满+最小值
f[i,j]:=min{f[i-1,j-K*w[i]]+K*p[i]}(k>=0)=min{f[i-1,j],f[i-1,j-K*w[i]]+K*p[i]}(k>=1)
f[i-1,j-K*w[i]]+K*p[i](K>=1)
=min{f[i-1,j], f[i-1,(j-w[i])-k*w[i]]+k*p[i]+p[i](K>=0)}
=min{ f[i-1,j], f[i,(j-w[i])+p[i]}
初始值(在没有任何物品可以放入背包时的合法状态):
f[0]=0; //容量为0的背包可能被价值为0的nothing“恰好装满”
f[1~n]=+∞ //其它容量的背包均没有合法的解,属于未定义的状态,本题又是求最小值,则初始值就应该是∞了。
1 const 2 maxm=20000; 3 maxnum=30000000; 4 var 5 e,ff,n,m,t,i:longint; 6 p,w:array[0..600] of longint; 7 f:array[0..20000]of longint; 8 procedure init; 9 var i:longint; 10 begin 11 // assign(input,'pig.in');reset(input); 12 13 readln(e,ff); 14 m:=ff-e; 15 readln(n); 16 for i:=1 to n do readln(p[i],w[i]); 17 // close(input); 18 end; 19 procedure wqdp; 20 var i,j:longint; 21 begin 22 f[0]:=0; 23 for i:=1 to maxm do f[i]:=maxnum; 24 for i:=1 to n do 25 for j:=1 to m do 26 if (j>=w[i]) and(f[j]>f[j-w[i]]+p[i]) then 27 f[j]:=f[j-w[i]]+p[i]; 28 end; 29 procedure print; 30 begin 31 if f[m]=maxnum then writeln('This is impossible.') 32 else writeln('The minimum amount of money in the piggy-bank is ',f[m],'.'); 33 end; 34 begin 35 // readln(t); 36 // for i:=1 to t do 37 // begin 38 init; 39 wqdp; 40 print; 41 // end; 42 end.