题意:农夫约翰要给奶牛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 ", ans); 42 } 43 return 0; 44 }