您的位置:首页 > 其它

【POJ 3040】Allowance

2016-07-23 16:47 417 查看
Allowance

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 ompute the maximum number of weeks he can pay Bessie.Input

Line 1: Two space-separated integers: N and C

Lines 2..N+1: Each line corresponds to a denomination of coin and contains two integers: the value V (1 <= V <= 100,000,000) of the denomination, and the number of coins B (1 <= B <= 1,000,000) of this denomation in Farmer John’s possession.

Output

Line 1: A single integer that is the number of weeks Farmer John can pay Bessie at least C allowance

Sample Input

3 6

10 1

1 100

5 120

Sample Output

111

题意:约翰要给他的牛贝西发工资,每天不得低于C元,约翰有n种面值的钱币,第i种的面值为v_i,数量有b_i。问这些钱最多给贝西发多少天的工资。注意,每种面值的金钱都是下一种的面值的倍数

题解:读完题题直接就蒙了~~,后来看完学长的题解思路一下子清晰多了~~~挺不错的一道题

这一题分三步解决:


按照面值从大到小取,面值大于等于C的,直接取光。

再按面值从大到小取,凑近C,可以小于等于C,但不能大于C。

最后从小到大取,凑满C,这里的凑满可以等于大于C。然后将上述 2,3步取到的面值全部取走,再转入步骤2,这样每次找到的取法就是当前最优取法,直到所剩下的金币总价值不够C结束。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define INF 0x3f3f3f
using namespace std;
int use[30];//记录当前取法的第i种面值取的个数
struct node{
int a,b;
}st[21];
int cmp(node i, node j)
{
return i.a<j.a;
}
int main()
{
int i,n,c,cot;
while(scanf("%d%d",&n,&c)!=EOF)
{
cot=0;
for(i=0;i<n;i++)
scanf("%d%d",&st[i].a,&st[i].b);
sort(st,st+n,cmp);
for(i=n-1;i>=0;i--)  //第一步,满足大于C的面值全部取走
{
if(st[i].a>=c)
{
cot+=st[i].b;
st[i].b=0;
}
}
int sign,cnt,k,m;
while(1)
{
sign=0;
cnt=c;
memset(use,0,sizeof(use));
for(i=n-1;i>=0;--i)//第二步,从大到小取,不能超过C的值
{
if(st[i].b)
{
k=cnt/st[i].a;
m=min(k,st[i].b);
cnt-=m*st[i].a;
use[i]=m;
if(cnt==0)
{
sign=1;
break;
}
}
}
if(cnt>0)
{
for(i=0;i<n;i++)//第三步,从小到大取,凑满C
{
if(st[i].b>use[i])
{
while(use[i]<st[i].b)
{
cnt-=st[i].a;
use[i]++;
if(cnt<=0)
{
sign=1;
break;
}
}
}
if(sign)
break;
}
}
if(!sign)
break;
m=INF;
for(i=0;i<n;i++)
{
if(use[i])
m=min(m,st[i].b/use[i]);
}
cot+=m;
for(i=0;i<n;i++)
{
if(use[i])//找到当前取法的能取的总次数
st[i].b-=m*use[i];
}
}
printf("%d\n",cot);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 贪心