林洪涛(林洪涛)11:09:06
今天晨会题目:
有n种经验石,经验值分别为exp[i],每种经验石个数为count[i],现在目标经验值是value,求:各种经验石的个数,保证超出部分最小化。(i= 0到n-1)
本题是由多重背包扩展的题目。参考资料《背包九讲》。
先看0-1背包类型
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
过程ZeroOnePack,表示处理一件01背包中的物品,两个参数cost、weight分别表明这件物品的费用和价值。
伪代码:
procedureZeroOnePack(cost,weight)
forv=V..cost
f[v]=max{f[v],f[v-cost]+weight}
注意这个过程里的处理与前面给出的伪代码有所不同。前面的示例程序写成v=V..0是为了在程序中体现每个状态都按照方程求解了,避免不必要的思维复杂度。而这里既然已经抽象成看作黑箱的过程了,就可以加入优化。费用为cost的物品不会影响状态f[0..cost-1],这是显然的。有了这个过程以后,01背包问题的伪代码就可以这样写:
fori=1..N
ZeroOnePack(c[i],w[i]);
C++代码:
for(i=1;i<=v; i++) f[i] = 0;
for(i= 0; i<num; i++)
for(int j=v; j>=C[i]; j--)
f[j]= max( f[j], f[j – C[i]] +W[j] );
例:若有价值3元、4元、5元、6元、7元硬币各一枚,花最少的硬币付清价值20元物品,求方案见表格(附件)
再回到题目,
先简化原题N= 4