標籤:多重背包
連結:poj 1276
題意:已知金額cash,給定幾種不同面值的貨幣的數量及面值,求利用給定的貨幣可以湊成
小於等於cash的金額的最大值
分析:因為每種貨幣的面值及數量已知,可以將其轉化為多重背包,背包的容量即為cash,
每個物品的價值及費用都為每種貨幣的面值。
多重背包可以轉化為01背包,不過這樣會逾時,為了避免這樣,可以轉化為完全背包和二進位思想的01背包
#include<stdio.h>#include<string.h>int f[100010],v;int max(int a,int b){ return a>b?a:b;}void zeroone(int cost,int weight) //01背包{ int i; for(i=v;i>=cost;i--) f[i]=max(f[i],f[i-cost]+weight);}void complete(int cost,int weight) //完全背包{ int i; for(i=cost;i<=v;i++) f[i]=max(f[i],f[i-cost]+weight);}void multiple(int num,int cost,int weight) //多重背包{ int k; if(num*weight>=v){ complete(cost,weight); return ; } for(k=1;k<num;k*=2){ zeroone(k*cost,k*weight); num-=k; } zeroone(num*cost,num*weight);}int main(){ int i,n,num[1010],w[1010]; while(scanf("%d",&v)!=EOF){ scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&num[i],&w[i]); memset(f,0,sizeof(f)); for(i=1;i<=n;i++) multiple(num[i],w[i],w[i]); printf("%d\n",f[v]); } return 0;}