1716: [Usaco2006 Dec]The Fewest Coins 找零钱
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1716: [Usaco2006 Dec]The Fewest Coins 找零钱相关的知识,希望对你有一定的参考价值。
n<=100种硬币,给每种的硬币的面额<=120和我每种有多少个<=10000,店主的硬币跟我一样但有无限个,求买t<=10000块钱的东西钱最少转手几次。
我拿的硬币最少几次就是多重背包,店主还的最少当然是完全背包啦,那问题在于这个背包多大呀?
找回来的钱和我给的钱一定没有交集,如果有,那当初少给点就好了。我们需要找钱,究其原因是要用给的钱若干减去找的钱若干凑到t。那么极端地,要凑t%vmax*2次才能凑到和t在%vmax同个值的数。而这意味着我们要多出最多vmax^2块钱。
看不懂就对了!代码在下面,要严谨去看看其他大爷的博客吧!
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m,t; 9 #define maxn 111 10 #define maxm 25011 11 int f[maxm],g[maxm],v[maxn],c[maxn]; 12 int que[maxm],head,tail,id[maxm],vmax; 13 const int inf=0x3f3f3f3f; 14 int main() 15 { 16 scanf("%d%d",&n,&t);vmax=0; 17 for (int i=1;i<=n;i++) scanf("%d",&v[i]),vmax=max(vmax,v[i]); 18 for (int i=1;i<=n;i++) scanf("%d",&c[i]); 19 int m=t+vmax*vmax; 20 f[0]=g[0]=0;for (int i=1;i<=m;i++) f[i]=g[i]=inf; 21 for (int i=1;i<=n;i++) 22 for (int j=0;j<v[i];j++) 23 { 24 head=tail=0; 25 for (int k=0,now;(now=k*v[i]+j)<=m;k++) 26 { 27 int tmp=f[now]-k; 28 while (head<tail && que[tail-1]>tmp) tail--; 29 while (head<tail && id[head]<k-c[i]) head++; 30 que[tail]=tmp;id[tail++]=k; 31 f[now]=min(inf,que[head]+k); 32 } 33 } 34 for (int i=1;i<=n;i++) 35 for (int j=0;j<v[i];j++) 36 { 37 int Min=inf; 38 for (int k=j;k<=m;k+=v[i]) 39 { 40 Min=min(Min,g[k]-k/v[i]); 41 g[k]=Min+k/v[i]; 42 } 43 } 44 int ans=inf; 45 for (int i=t;i<=m;i++) ans=min(ans,f[i]+g[i-t]); 46 printf("%d\n",ans==inf?-1:ans); 47 return 0; 48 }
以上是关于1716: [Usaco2006 Dec]The Fewest Coins 找零钱的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ1650][Usaco2006 Dec]River Hopscotch 跳石子
[BZOJ1715][Usaco2006 Dec]Wormholes 虫洞
[BZOJ] 1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐