SN祈祷中...

P2376 [USACO09OCT] Allowance G

简要题意

给你 种面值的货币,其中货币中面值小的货币的面值可以整除面值大的货币的面值,给你每种面值货币的数量。每周都要给贝茜发至少 元的工资,问最多能发多少周。

策略分析

首先对于面值大于 的货币,显然我们每周给出一张就行了,没有其它办法,所以可以直接把它们的数量加在答案中。接下来是对于面值小于 的货币,我们先对所有货币按照面值降序排序,每次选取能够选的最大的,然后再用最小的去填补剩下的那一点点价格缝隙,因为我们有小面值货币面值是大面值货币面值因数这个条件,所以最大配最小这种做法一定会产生最小的浪费,从而得到最优解。如果这一次凑不出来了,那显然是钱不够了,那么所有情况就统计完毕,输出答案即可。

参考代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define PII pair<int, int>
using namespace std;

namespace SHAWN {
vector<PII> v;
//v.first 代表面值,v.second 代表货币数量
int n, c, ans;
bool cmp(PII x, PII y) { return x.first > y.first; }
int work()
{
cin >> n >> c;
for (int i = 1, val, b; i <= n; ++i) {
cin >> val >> b;
if (val >= c) { ans += b; }
else { v.push_back({val, b}); }
}
sort(v.begin(), v.end(), cmp);
while (true) {
int tmp = c;
for (int i = 0; i < v.size(); ++i) {
while (tmp && v[i].second && tmp >= v[i].first) {
tmp -= v[i].first;
--v[i].second;
}
}
if (tmp > 0) {
for (int i = v.size() - 1; i >= 0; --i) {
if (v[i].second && v[i].first >= tmp) {
tmp -= v[i].first;
--v[i].second;
break;
}
}
}
if (tmp > 0) { break; }
++ans;
}
cout << ans << '\n';
return 0;
}
}

signed int main() {
ios :: sync_with_stdio(false);
cin.tie(nullptr);
return SHAWN :: work();
}