题解:B3745 [语言月赛202304] 你的牌太多了
Solution
选择与扶苏本轮打出的牌花色相同且点数大于扶苏打出的牌中点数最小的一张打出。
上面这句话是题目的核心。
首先,必然要开题目描述中的 4 个数组 f1, p1, f2, p2,然后由于已经打出的牌无法再次打出,所以需要开一个标记数组 b,其中 bi 表示小 F 的第 i 张牌是否被打出。
接下来,对于每一个 p,我们需要找到符合要求的牌。遍历 1 ∼ n,不符合如下条件就需要跳过: - bi = true ,即第 i 张牌已经被选择; - f2i ≠ f1p,即两张牌花色不同; - p2i ≤ p1p,即小 F 的这张牌的花色不大于扶苏打出的牌的花色。
接下来,题目要求找到牌中点数最小的一张打出。所以我们需要一个记录答案编号的变量
最后如果可以打出牌的话,那么要将 bi 设为 true 。
最后结果就是统计 bi 中结果为
false ,即未被打出的牌的数量。 ###
Code 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
const int N = 110;
bool b[N]; // 标记小 F 的牌是否被使用
int n, m, r, f1[N], p1[N], f2[N], p2[N] = {(int)2e9};
// p2[0] = 2e9 是因为 minn 初始值为 0,且应该是 inf
int read() { int x; std::cin >> x; return x; }
int main() {
// 读入
std::cin >> n >> m >> r;
std::generate_n(f1 + 1, n, read);
std::generate_n(p1 + 1, n, read);
std::generate_n(f2 + 1, n, read);
std::generate_n(p2 + 1, n, read);
// 模拟
for (int t = 1, p; t <= n; ++t) {
std::cin >> p;
int minn = 0; // 出的牌的编号
for (int i = 1; i <= n; ++i)
if (!b[i] && f2[i] == f1[p] && p2[i] > p1[p] && p2[i] < p2[minn]) minn = i;
if (minn) b[minn] = true;
}
// 统计
// std::count(begin, end, val),统计 [begin,end) 区间内 val 的数量
std::cout << std::count(b + 1, b + n + 1, false) << std::endl;
return 0;
}
