您的位置:首页 > 其它

poj3040Allowance

2016-04-01 20:30 330 查看
题意:农夫约翰要给奶牛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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: