天天看点

POJ 3040 Allowance (贪心)

Allowance

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1696 Accepted: 708

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      

= = 贪心思路比较明显 但是不是很好写 先从大到小尝试拼凑一次工资量 然后不够的用一个小的补齐

最后确定发工资量 然后更新剩余的硬币 在尝试后仍不能拼凑一次工资量 就退出循环

- - 贪心模拟感觉不好很好写 还是代码能力不够 想的不够多

AC代码如下:

//
//  POJ 3040 Allowance
//
//  Created by TaoSama on 2015-02-22
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
#define CLR(x,y) memset(x, y, sizeof(x))

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

struct Coin {
	int v, c;
	bool operator<(const Coin& rhs) const {
		return v > rhs.v;
	}
} a[25];
int n, p, need[25];

int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	ios_base::sync_with_stdio(0);

	while(cin >> n >> p) {
		for(int i = 1; i <= n; ++i)
			cin >> a[i].v >> a[i].c;
		sort(a + 1, a + 1 + n);
		int ans = 0;
		while(true) {
			int rest = p; 		//发一次工资
			memset(need, 0, sizeof need);
			for(int i = 1; i <= n; ++i) {   //从大到小尝试
				if(a[i].c > 0) {
					int t = min(a[i].c, rest / a[i].v);
					rest -= t * a[i].v;
					need[i] = t;
				}
				if(rest == 0) break;
			}
			if(rest > 0) {
				for(int i = n; i > 0; --i) { //用小的补齐 抑或最后大于p的
					if(a[i].c > 0 && a[i].v >= rest) {
						rest = 0;
						++need[i];
						break;
					}
				}
			}
			if(rest > 0) break;  //还剩下的说明不能了
			int add = INF;
			for(int i = 1; i <= n; ++i) //获取发工资次数
				if(need[i])
					add = min(add, a[i].c / need[i]);
			for(int i = 1; i <= n; ++i) //更新剩余硬币
				if(need[i])
					a[i].c -= add * need[i];
			ans += add;
		}
		cout << ans << endl;
	}
	return 0;
}