poj3040Allowance

题意:农夫约翰要给奶牛Bessie发工资了 ,每周至少 C 元。约翰手头上有面值V_i的硬币B_i个,这些硬币的最小公约数为硬币的最小面值。求最多能发几周?
思路:首相将面额大于等于C的硬币,直接发送。对于生下硬币,先从大到小排序,凑出最接近C的面额,不超过C,然后在从小到大,凑出刚好大于等于C的面额。然后修改它们数量,一直重复这个操作。最后所有都凑不出C为止,思路好想,操作不好写。

#include<cstdio>
#include<cstring>
#include<functional>
#include<limits>
#include<algorithm>
#include<iostream>
#define fi first
#define se second
using namespace std;
typedef pair<int,int>Coin;
Coin a[20];
int need[20];
int main()
{
    int n,c;
     while(~scanf("%d%d",&n,&c)){
        for(int i=0;i<n;i++) scanf("%d%d",&a[i].fi,&a[i].se);
        int ans=0;
        for(int i=0;i<n;i++){
            if(a[i].fi>=c){
                ans+=a[i].se;
                a[i].se=0;
            }
        }
        sort(a,a+n,greater<Coin>());
        while(1){
            int sum=c;
            memset(need,0,sizeof(need));
            for(int i=0;i<n;i++){
                if(sum>0&&a[i].se>0){
                    need[i]=min(a[i].se,sum/a[i].fi);
                    sum-=need[i]*a[i].fi;
                }
            }
            for(int i=n-1;i>=0;i--){
                if(sum>0&&a[i].se>0){
                    int cause=min(a[i].se-need[i],(sum+a[i].fi-1)/a[i].fi);//允许不超过一个面值的sum
                    if(cause>0){
                        need[i]+=cause;
                        sum-=cause*a[i].fi;
                    }
                }
            }
            if(sum>0) break;
            int add=0x7ffffff;
            for(int i=0;i<n;i++){
                if(need[i]==0) continue;
                add=min(add,a[i].se/need[i]);
            }
            ans+=add;
            for(int i=0;i<n;i++){
              if(need[i]==0) continue;
               a[i].se-=add*need[i];
            }
        }
        printf("%d\n",ans);
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值