POJ 3260 The Fewest Coins(背包问题)
【题目链接】 http://poj.org/problem?id=3260
【题目大意】
给出你拥有的货币种类和每种的数量,商店拥有的货币数量是无限的,
问你买一个价值为m的物品,最少的货币流通数量为多少
【题解】
我们可以计算出买不同价值的物品,在没有找钱情况下的最少用币数量,
记为dp[i],这个可以用多重背包来完成,对于商店来说,我们可以计算出,
对于不同额度的找零,最少用币数量,记为f[i],
我们发现,对于货币流通最少,就是求dp[i+m]+f[i]的最小值,
由鸽巢原理可得我们只要计算maxw*maxw+m的dp值就可以了。
【代码】
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; int m,n,w[110],c[110],dp[24563],f[24563]; int main(){ while(~scanf("%d%d",&n,&m)){ int maxn=0; for(int i=1;i<=n;i++)scanf("%d",&w[i]),maxn=max(maxn,w[i]); for(int i=1;i<=n;i++)scanf("%d",&c[i]); maxn=maxn*maxn+m+1; memset(dp,INF,sizeof(dp)); dp[0]=0; for(int i=1;i<=n;i++){ if(c[i]*w[i]>=maxn){ for(int j=w[i];j<=maxn;j++)dp[j]=min(dp[j],dp[j-w[i]]+1); }else{ for(int k=1;k<c[i];k<<=1){ for(int j=maxn;j>=w[i]*k;j--)dp[j]=min(dp[j],dp[j-w[i]*k]+k); c[i]-=k; }for(int j=maxn;j>=w[i]*c[i];j--)dp[j]=min(dp[j],dp[j-w[i]*c[i]]+c[i]); }memset(f,INF,sizeof(f));f[0]=0; } for(int i=1;i<=n;i++){ for(int j=w[i];j<=maxn;j++)f[j]=min(f[j],f[j-w[i]]+1); }int ans=INF; for(int i=0;i<=maxn-m;i++)ans=min(ans,dp[i+m]+f[i]); if(ans==INF)ans=-1; printf("%d\n",ans); }return 0; }
愿你出走半生,归来仍是少年