POJ 3040 Allowance

题意:农夫约翰要给奶牛Bessie发工资了,每周至少 C 元。

          约翰手头上有面值V_i的硬币B_i个,这些硬币的最小公约数为硬币的最小面值。求最多能发几周?

分析:使用贪心的策略,分三个步骤

          1.把面值大于c的硬币直接统统发完  

     2.面值从大往小取,把面值凑到最大但不大于等于c,同时减少使用的硬币数量

     3.面值从小往大取,把面值凑到刚好大于等于c,同时减少使用的硬币数量,再重复第二步

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int MAX_N = 20;
 6 int n, c;
 7 typedef pair<int, int> P;
 8 P a[MAX_N];
 9 bool compare(P x, P y) {
10     return x.first > y.first;
11 }
12 int main() {
13     while(scanf("%d%d", &n, &c) != EOF) {
14         int v, m;
15         int count = 0, ans = 0;
16         for(int i = 0; i < n; i++) scanf("%d%d", &a[i].first, &a[i].second);
17         sort(a, a+n, compare);
18         int j = 0;
19         for(; j < n; j++) {
20             if(a[j].first < c) break;
21         }
22         for(int i = 0; i < j; i++) ans += a[i].second;24         while(1) {
25             int now = 0;
26             for(int i = j; i < n; i++) {
27                 while(a[i].second && now + a[i].first < c) {
28                     now += a[i].first;
29                     a[i].second--;
30                 }
31             }
32             for(int i = n-1; i >= j; i--) {
33                 while(a[i].second && now < c) {
34                     now += a[i].first;
35                     a[i].second--;
36                 }
37             }
38             if(now < c) break;
39             ans++;
40         } 
41         printf("%d\n", ans);
42     }
43     return 0;
44 }

 

posted on 2018-03-17 10:36  kindleheart  阅读(225)  评论(0编辑  收藏  举报