POJ1276 - Cash Machine(多重背包)
题目大意
给定一个容量为M的背包以及n种物品,每种物品有一个体积和数量,要求你用这些物品尽量的装满背包
题解
就是多重背包~~~~用二进制优化了一下,就是把每种物品的数量cnt拆成由几个数组成,1,2,4,~~~cnt-2^K+1,k满足cnt-2^K+1>0的最大整数,体积和价值乘上相应的数就是相应物品的价值和体积,这样用这些物品能够表示1~~cnt所有的情况~~~这就转化成01背包了~~~
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define MAXN 100005 int dp[MAXN]; int value[15],cnt[15]; int cash,n; void CompletePack(int c,int w) { for(int i=c; i<=cash; i++) dp[i]=max(dp[i],dp[i-c]+w); } void ZeroOnePack(int c,int w) { for(int i=cash; i>=c; i--) dp[i]=max(dp[i],dp[i-c]+w); } void MultiplePack(int c,int w,int m) { if(c*m>=cash) { CompletePack(c,w); return; } int k=1; while(k<m) { ZeroOnePack(k*c,k*w); m-=k; k*=2; } if(m>0) ZeroOnePack(c*m,w*m); } int main() { while(scanf("%d",&cash)!=EOF) { scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d%d",&cnt[i],&value[i]); memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++) MultiplePack(value[i],value[i],cnt[i]); printf("%d\n",dp[cash]); } return 0; }