poj3040

一、题意:约翰要给他的牛贝西发工资,每天不得低于C元,约翰有n种面值的钱币,第i种的面值为v_i,数量有b_i。问这些钱最多给贝西发多少天的工资。注意,每种面值的金钱都是下一种的面值的倍数。

二、思路:分三步解决:1. 按照面值从大到小取,面值大于等于C的,直接取光。2. 再按面值从大到小取,凑近C,可以小于等于C,但不能大于C.3.最后从小到大取,凑满C,这里的凑满可以等于大于C。然后将上述2,3步取到的面值全部取走,再转入步骤2,这样每次找到的取法就是当前最优取法,直到所剩下的金币总价值不够C结束。

三、代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <queue>
 6 #include <algorithm>
 7 #define MAXN 11111
 8 #define MAXM 222222
 9 #define INF 1000000000
10 using namespace std;
11 int n, c;
12 typedef pair<int, int> P;
13 P a[22];
14 int use[22], sum[22];
15 int main()
16 {
17     scanf("%d%d", &n, &c);
18     for(int i = 0; i < n; i++) scanf("%d%d", &a[i].first, &a[i].second);
19     sort(a, a + n);
20     int ans = 0;
21     for(int i = n - 1; i >= 0; i--)
22         if(a[i].first >= c)
23         {
24             ans += a[i].second;
25             a[i].second = 0;
26         }
27     while(true)
28     {
29         int flag = 0;
30         int tmp = c;
31  
32         memset(use, 0, sizeof(use));
33         for(int i = n - 1; i >= 0; i--)
34             if(a[i].second)
35             {
36                 int k = tmp / a[i].first;
37                 int mi = min(a[i].second, k);
38                 tmp -= mi * a[i].first;
39                 use[i] = mi;
40                 if(tmp <= 0)
41                 {
42                     flag = 1;
43                     break;
44                 }
45             }
46         if(tmp > 0)
47         {
48             for(int i = 0; i < n; i++)
49                 if(a[i].second > use[i])
50                 {
51                     while(use[i] < a[i].second)
52                     {
53                         tmp -= a[i].first;
54                         use[i]++;
55                         if(tmp <= 0)
56                         {
57                             flag = 1;
58                             break;
59                         }
60                     }
61                     if(tmp <= 0) break;
62                 }
63         }
64         if(!flag) break;
65         int mx = INF;
66         for(int i = n - 1; i >= 0; i--)
67         if(use[i]) mx = min(mx, a[i].second / use[i]);
68         ans += mx;
69         for(int i = n - 1; i >= 0; i--)
70             if(use[i]) a[i].second -= mx * use[i];
71  
72     }
73     printf("%d
", ans);
74     return 0;
75 }
View Code

  

原文地址:https://www.cnblogs.com/acm-jing/p/9833190.html