POJ-----3040贪心

Allowance
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2921 Accepted: 1178

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

老板要给员工发工资,有1,5,10,50面值的美分硬币,每周最少付c美分,问最多能付多少周

先按面值大的来,刚开始想错了,想取一个大,在凑几个小,睡了一觉缓缓脑子想明白了

从大一直取到到小,不能超过c,少了用小的补,才是最优


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
	int dem, num;
}co[1010];
bool cmp(node x, node y){
	return x.dem < y.dem;
}
int need[1010];
int main(){
	int rest, lim, ans, t, m, n, c;
	while(scanf("%d%d", &n, &c) == 2){
		for(int i = 0; i < n; i++){
			scanf("%d%d", &co[i].dem, &co[i].num);
		}
		ans = 0;
		t = 1e8;
		sort(co, co+n, cmp);
		for(lim = n-1; lim >= 0; lim--){//先把面额超过工资的取完
			if(co[lim].dem >= c){
				ans += co[lim].num;
				continue;
			}
			break;
		}
		while(1){
			rest = c;
			memset(need, 0, sizeof(need));
			for(int i = lim; i >= 0; i--){//计算每种方式各种硬币硬币各需要多少个加一块接近c但不超过c
				if(!co[i].num || !rest){
					continue;
				}
				t = rest / co[i].dem;
				t = min(t, co[i].num);
				need[i] = t;
				rest -= t * co[i].dem;
			}
			if(rest){//如果不是正好相等就用小的补
				for(int i = 0; i <= lim; i++){
					if(rest <= co[i].dem && (co[i].num - need[i])){//上面已经确定最接近c,所以只需一个最小的硬币就够了
						need[i]++;
						rest = 0;
						break;
					}
				}
				if(rest){//如果没有,就说明钱不够了,结束
					break;
				}
			}
			m = 1e8;
			for(int i = 0; i <= lim; i++){
				if(need[i]){
					m = min(m, co[i].num / need[i]);
				}
			}
			ans += m;
			for(int i = 0; i <= lim; i++){
				co[i].num -= m * need[i];
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值