[Usaco2005 Oct]Allowance 津贴

来源:互联网 发布:庞氏骗局知乎 编辑:程序博客网 时间:2024/04/28 16:22

Description
As a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has a set of coins in N (1 <= N <= 20) different denominations, where each denomination of coin evenly divides the next-larger denomination (e.g., 1 cent coins, 5 cent coins, 10 cent coins, and 50 cent coins). Using the given set of coins, he would like to pay Bessie at least some given amount of money C (1 <= C <= 100,000,000) every week. Please help him compute the maximum number of weeks he can pay Bessie.
作为对勤勤恳恳工作的贝茜的奖励,约翰已经决定开始支付贝茜一个小的每周津贴。 约翰有n(1N20)种币值的硬币,面值小的硬币总能整除面值较大的硬币。比如说,币值有如下几种:1美分,5美分,10美分,50美分……利用给定的这些硬币,他将要每周付给贝茜一定金额的津贴C(1C108)
请帮他计算出他最多能给贝茜发几周的津贴。

Input
第1行:2个用空格隔开的整数nC
第2到n+1行:每行两个整数表示一种币值的硬币.第一个整数V(IV108),表示币值。
第二个整数B(1B106),表示约翰拥有的这种硬币的个数。

Output
一个整数,表示约翰付给贝茜津贴得最多的周数。

Sample Input
3 6
10 1
1 1 00
5 1 20

Sample Output
111

样例说明
约翰想要每周付给贝茜6美分。他有1个10美分的硬币、100个1美分的硬币、120个5美分的硬币。约翰可以第一周付给贝茜一个10美分的硬币,接着的10周每周付给贝茜2个5美分硬币,接下来的100周每周付给贝茜一个1美分的硬币和1个5美分的硬币。共计111周。

HINT

Source
Silver

解题思路
贪心,具体请见代码

代码

#include <cstdio>#include <algorithm>const int maxn=20;struct data{    int price,lim;    bool operator <(const data &b) const    {        return price<b.price;    }};int n,c,ans;data d[maxn+2];int main(){    scanf("%d%d",&n,&c);    for(int i=1; i<=n; i++)    {        scanf("%d%d",&d[i].price,&d[i].lim);    }    std::sort(d+1,d+n+1);//按价格从小到大排序    while(n)    {        if(d[n].price>=c)//如果当前钞票的面值大于需要的面值        {            ans+=d[n].lim;//最优方案一定是每周付一张当前面值的钞票            n--;        }        else        {            break;        }    }    while(1)    {        int r=0;        for(int i=n; i>0; i--)        {            while((d[i].price+r<=c)&&(d[i].lim>0))            {//如果当前面值的钞票不会使需要支付的面值过量                d[i].lim--;//那么使用当前钞票                r+=d[i].price;            }        }        if(r<c)        {//如果不够支付一周            for(int i=1; i<=n; i++)            {//从剩下的面值当中挑一张最小的                if((r+d[i].price>=c)&&(d[i].lim>0))                {                    d[i].lim--;                    r+=d[i].price;                    break;                }            }        }        if(r>=c)        {            ans++;        }        else        {//如果还不够,说明所有钞票已经用完            printf("%d\n",ans);            return 0;        }    }}
原创粉丝点击