zoukankan      html  css  js  c++  java
  • 【贪心】Allowance POJ 3040

    题目链接: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
    ",ans);
    	return 0;
    }
  • 相关阅读:
    Co.
    编程
    编程
    编程
    数据同步
    Co.
    Co.
    Co.
    Co.
    sss
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039517.html
Copyright © 2011-2022 走看看