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\n", ans);
74     return 0;
75 }
View Code
复制代码

 

  

 

posted @   Run_For_Love  阅读(753)  评论(0编辑  收藏  举报
编辑推荐:
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
阅读排行:
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· “你见过凌晨四点的洛杉矶吗?”--《我们为什么要睡觉》
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
点击右上角即可分享
微信分享提示