poj 3040 Allowance

来源:互联网 发布:关于美食的评价知乎 编辑:程序博客网 时间:2024/05/23 11:04

原题: http://poj.org/problem?id=3040

//题目大意:John每个星期都要给Bessie工资,每个星期的工资>=C,即每个星期最低工资为C,现在John有N种不同面额的硬币,要求出John最多能付给Bessie多少个星期的工资?//思路 : 将硬币大致分成两类, ①面额小于每个月最低工资的硬币,②面额大于或等于最低工资的硬币//      1.硬币面额大于最低工资,那就每个星期给一个硬币即可,所以这类的硬币的个数就是 John 所能支付给Bessie的星期数//      2.硬币面额小于最低工资,那我们就要用它们凑到 >=C,我们凑的过程要尽量避免浪费,方案如下。 //       凑钱方案:对于给定的C,我们先用较大的面额(从大到小遍历)的硬币去凑到最接近C,即小于或等于C,如果不能刚好凑到C,即<C,我们再用面额较小(由小到大遍历)的硬币去凑,直到恰好好比C终止,星期数+1,重复循环,直到最后硬币不够凑到>=C了即可//       最后把1、2的星期数 相加。 //想了很久,千辛万苦,错了两次,终于AC,激动。#include<iostream> #include<cstdio>#include<algorithm> #include<math.h> #define qwq 0x7fffffffusing namespace std;struct Coin{    int vi;    int ni;}coin[21];int cmp(Coin a,Coin b){    return a.vi<b.vi;}int main(){    int n,m;    while(~scanf("%d %d",&n,&m))    {        for(int i=0;i<n;i++)        {            scanf("%d %d",&coin[i].vi,&coin[i].ni);        }        sort(coin,coin+n,cmp);        int pos=-1;        for(int i=0;i<n;i++)        {            if(coin[i].vi>=m)            {                pos=i;                break;            }        }        int ans=0;        if(pos!=-1){//找到面额>=m的硬币             for(int i=pos;i<n;i++)            {                ans+=coin[i].ni;            }        }else{//未找到             pos=n;        }//        printf("ans=%d\n",ans);        while(true)        {            int rest=m;            for(int i=pos-1;i>=0;i--) //从大到小遍历,尽量最接近C,但不超过C             {                if(coin[i].ni==0)continue;                if(coin[i].vi>rest)continue;                int ni=coin[i].ni;                int vi=coin[i].vi;                int need=rest/vi;                if(need>coin[i].ni)                {                    need=coin[i].ni;                    coin[i].ni=0;                }else{                    coin[i].ni=coin[i].ni-need;                }                rest=rest-need*vi;                if(rest==0){                    ans++;                    break;                }            }            if(rest>0) //凑不到等于C,即<C             {                for(int i=0;i<=pos-1;i++)//用面额小的,从小到大去凑直到>C                 {                    if(coin[i].ni==0)continue;                    int ni=coin[i].ni;                    int vi=coin[i].vi;                    int need=rest/vi;                    if(rest%vi)                    {                        need++;                    }                    if(need>coin[i].ni)                    {                        need=coin[i].ni;                        rest=rest-need*vi;                        coin[i].ni=0;                    }else{ //need<coin[i].ni                        rest=0;                        coin[i].ni=coin[i].ni-need;                    }                    if(rest==0){                        ans++;                        break;                    }                }                if(rest>0){//凑不到C了,结束                     break;                }            }        }        printf("%d\n",ans);    }    return 0;}      


原创粉丝点击