题解:B3745 [语言月赛202304] 你的牌太多了

· · 题解

\textbf{Solution}

选择与扶苏本轮打出的牌花色相同且点数大于扶苏打出的牌中点数最小的一张打出。

上面这句话是题目的核心。

首先,必然要开题目描述中的 4 个数组 f_1,p_1,f_2,p_2,然后由于已经打出的牌无法再次打出,所以需要开一个标记数组 b,其中 b_i 表示小 F 的第 i 张牌是否被打出。

接下来,对于每一个 p,我们需要找到符合要求的牌。遍历 1\sim n,不符合如下条件就需要跳过:

接下来,题目要求找到牌中点数最小的一张打出。所以我们需要一个记录答案编号的变量 \rm minn,初始的时候对应牌的编号可以设置为 \inf,然后遍历时如果牌都满足上面的条件且点数小于 \rm minn 这张牌的点数,那么就更新 \rm minn

最后如果可以打出牌的话,那么要将 b_i 设为 \operatorname{true}

最后结果就是统计 b_i 中结果为 \operatorname{false},即未被打出的牌的数量。

\textbf{Code}

#include <iostream>
#include <algorithm>
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;
}