#POJ3040#Allowance(贪心经典)

15 篇文章 0 订阅

Allowance
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 3887 Accepted: 1563

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

Hint

INPUT DETAILS: 
FJ would like to pay Bessie 6 cents per week. He has 100 1-cent coins,120 5-cent coins, and 1 10-cent coin. 

OUTPUT DETAILS: 
FJ can overpay Bessie with the one 10-cent coin for 1 week, then pay Bessie two 5-cent coins for 10 weeks and then pay Bessie one 1-cent coin and one 5-cent coin for 100 weeks.


题意:

农夫约翰决定给奶牛贝西津贴,每周至少给C元。

他有N种硬币,硬币的面值从小到大排列,一个是下一个更大值的约数。

告诉你每种硬币的面值、数量,请问农夫约翰最多可以坚持给多少周。


硬币不能拆,每周只能多给不能少,这个题我倒是挺有感觉的,

但是当时一直都不知道要怎么把多种硬币凑一起,很伤,后来看了一些题解,才渐渐明白过来,还是自己这种类型的数学基础不太好


将硬币从小到大排序,从后往前扫描,那种直接能支付的大硬币就直接支付了。

对于小硬币,我们一次一次地凑,先从大往小凑,看一周的剩余价值中最多可以使用多少这种硬币,并记录(而且要减去已经凑好的)

然后如果还没凑够,就从小向大一个一个地加上,看能不能达到,如果能就记录并开始下一轮的凑,

如果不能就退出(此时一定再也不能凑出了,请想一想)


Code:

Status Accepted
Memory 668kB
Length 1790
Lang G++
Submitted
Shared

#include<iostream> 
#include<cstdio> 
#include<cstdlib> 
#include<cmath> 
#include<algorithm> 
#include<vector> 
#include<queue> 
#include<cstring> 
using namespace std; 
  
const int Max = 20; 
  
struct node{ 
    int p, num; 
    bool operator < (const node & X) const{ 
        return p < X.p;
    } 
}Coin[Max + 5]; 
  
int N, C; 
int Usenow[Max + 5];
  
bool  getint(int & num){ 
    char c;    int flg = 1;    num = 0; 
    while((c = getchar()) < '0' || c > '9'){ 
        if(c == '-')    flg = -1; 
        if(c == -1)     return 0; 
    } 
    while(c >= '0' && c <= '9'){     
        num = num * 10 + c - 48; 
        if((c = getchar()) == -1)   return 0; 
    } 
    num *= flg; 
    return 1; 
} 
/*
int Find(int lft, int r){
	int l = 1, mid, rt = 0;
	while(l <= r){
		mid = (l + r) >> 1;
		if(Coin[mid].p >= lft)
			rt = mid, r = mid - 1;
		else l = mid + 1;
	}
	return rt;
}*/
int main(){
	while(getint(N) && getint(C)){
		for(int i = 1; i <= N; ++ i)
			getint(Coin[i].p), getint(Coin[i].num);
		sort(Coin + 1, Coin + 1 + N);
		int Ans = 0;
		for(; N >= 1 && Coin[N].p >= C; Ans += Coin[N].num, -- N);
		while(1){
			int lft = C, num;
			for(int i = N; i >= 1; -- i){
				num = min(Coin[i].num, lft / Coin[i].p);
				lft -= num * Coin[i].p;
				Usenow[i] = num;
			}
			if(lft > 0){//only one coin	(not one kind of coin)
				for(int i = 1; i <= N; ++ i)	if(Coin[i].num && lft - Coin[i].p <= 0){
					++ Usenow[i];
					lft -= Coin[i].p;
					break;
				}
			}
			if(lft > 0)	break;
			else {
				int tmp = 0x3f3f3f3f;
				for(int i = 1; i <= N; ++ i)	if(Usenow[i])
					tmp = min(tmp, Coin[i].num / Usenow[i]);
				Ans += tmp;
				for(int i = 1; i <= N; ++ i)	if(Usenow[i])
					Coin[i].num -= tmp * Usenow[i], Usenow[i] = 0;
			}
		}
		printf("%d\n", Ans);
	}
    return 0; 
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值