多重背包 可行性+路径记录
题意是说你要用很多其它的零钱去买咖啡。最后输出你分别要用的 1,5 ,10 。25 的钱的数量。
多重背包二进制分解。然后记录下 这个状态。最后逆向推就可以。
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<cmath> #define INF 0x7fffffff #define eps 1e-6 #define LL long long using namespace std; int dp[10001]; int cot[4]; int value[]={1,5,10,25}; int n; struct lx { int va,co; }v[10001]; int zero(int cost,int i,int co) { cost*=co; for(int j=n;j>=cost;j--) if(dp[j-cost]+co>dp[j]) { dp[j]=dp[j-cost]+co; v[j].va=i; v[j].co=co; } } int main() { while(scanf("%d",&n)) { for(int i=0;i<4;i++) scanf("%d",&cot[i]); if(n==0)return 0; for(int i=0;i<=n;i++) dp[i]=-100001; dp[0]=0; for(int i=0;i<4;i++) { if(cot[i]==0)continue; if(value[i]*cot[i]>=n) { for(int j=value[i];j<=n;j++) if(dp[j-value[i]]+1>dp[j]) { dp[j]=dp[j-value[i]]+1; v[j].va=i; v[j].co=1; } } else { int k=1; int tmp=cot[i]; while(k<tmp) { zero(value[i],i,k); tmp-=k; k*=2; } zero(value[i],i,tmp); } } if(dp[n]<=0)puts("Charlie cannot buy coffee."); else { // for(int i=0;i<=n;i++) // printf("%d : %d*%d ",i,v[i].co,v[i].va); memset(cot,0,sizeof(cot)); while(n) { int i=v[n].va; int co=v[n].co; cot[i]+=co; // printf("%d == ",co); n-=value[i]*co; } printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters. ",cot[0],cot[1],cot[2],cot[3]); } } }