poj 1742 多重背包
题意:给出n种面值的硬币, 和这些硬币每一种的数量, 要求求出能组成的钱数(小于等于m)
思路:一开始直接用多重背包套上去超时了,然后就没辙了,然后参考网上的,说只需要判断是否能取到就行了,并不需要记录其价格,直接用bool判断是否能取到。就不会TLE了。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m; int v,sum; int a[200],b[200]; bool dp[100010]; /*完全背包*/ void CompletePack(int cost,int weight) { for(int i=cost;i<=v;i++) { dp[i]|=dp[i-cost]; } return; } /*01背包*/ void ZeroOnePack(int cost,int weight) { for(int i=v;i>=cost;i--) { dp[i]|=dp[i-cost]; } return; } /*多重背包*/ void MultiplePack(int cost,int weight,int amount) { if(cost*amount>=v) { CompletePack(cost,weight); return; } /*二进制优化*/ int k=1; while(k<amount) { ZeroOnePack(k*cost,k*weight); amount-=k; k*=2; } ZeroOnePack(amount*cost,amount*weight); return; } int main(int i) { while(scanf("%d%d",&n,&m)!=EOF,n+m) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } v=m; for(int i=0;i<=m;i++) dp[i]=0; dp[0]=1; for(int i=1;i<=n;i++) { scanf("%d",&b[i]); MultiplePack(a[i],a[i],b[i]); } int ans=0; for(int i=1;i<=m;i++) { if(dp[i]) ans++; } printf("%d\n",ans); } return 0; }