【贪心】Allowance POJ 3040

来源:互联网 发布:centos 7iso镜像安装 编辑:程序博客网 时间:2024/05/20 05:53

题目链接:http://poj.org/problem?id=3040

题目大意:你有n种不同面值的硬币,面值为vi的有bi个。“硬币的面额均匀地分配下一个更大的面额”,即下一个更大的硬币面值是此面值的倍数。你一周需要支付至少c元,没有退钱,每次只能给一周的钱。问最多能支撑几周。


首先对于面值大于c的硬币每个支撑一周。然后从大到小填充c直到填不下或刚好满,如果刚好满就打个标记、ans++。否则从小到大填充直到填满或大于。这里有一个优化,就是每次你配对出来一个方案,可以保存每种用了多少,然后把这些组成一个套装(k为最大目前可用套数),来支撑k个周。

贴代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct node{int v,b;friend bool operator <(node x,node y){return x.v<y.v;}}a[25];int use[25];int main()  {int n,c,ans=0;scanf("%d%d",&n,&c);for(int i=1;i<=n;i++)scanf("%d%d",&a[i].v,&a[i].b);sort(a+1,a+n+1);for(int i=n;i>=1;i--){if(a[i].v<c) break;ans+=a[i].b;a[i].b=0;}while(1){bool flag=0;int tmp=c;memset(use,0,sizeof use);for(int i=n;i>=1;i--){if(a[i].b==0)continue;use[i]=tmp/a[i].v;tmp-=min(use[i],a[i].b)*a[i].v;a[i].b-=min(use[i],a[i].b);if(tmp==0){ans++;flag=1;break;}}if(!flag){for(int i=1;i<=n;i++){if(a[i].b==0)continue;tmp-=a[i].v;a[i].b--;use[i]++;if(tmp<0){ans++;flag=1;break;}}}if(!flag)break;int k=100000000,mn;for(int i=1;i<=n;i++)if(use[i]){mn=a[i].b/use[i];k=min(k,mn);}for(int i=1;i<=n;i++)if(use[i])a[i].b-=k*use[i];ans+=k;}printf("%d\n",ans);return 0;}


原创粉丝点击