问题 A: 一场考试 提交: 445 | 解决: 42 | 时间限制: 1.00s | 内存限制: 256MB [ 提交 ] [状态] 题目描述 $n$ 个人参加一场考试,其中第 $i$ 个人的得分为 $a_i$现在至少需要发 $k$ 个证书。如果存在 $1 \le x, y \le n$,$a_x \ge a_y$ 且 $x$ 未拿到礼物但 $y$ 拿到证书,$x$ 会不满意。主办方希望每个人都满意,求颁发的证书数量的最小值。 输入 第一行两个整数 $n, k$。第二行 $n$ 个整数 $a_1, a_2, a_3, \dots, a_n$ 输出 一行一个整数,表示求得值。 输入输出样例 样例输入 #1 复制 5 3 75 95 120 75 41 样例输出 #1 复制 4 提示 样例为除了第五个人都有证书。数据范围:$1 \le k \le n \le 2000,1 \le a_i \le 120$。
时间: 2024-02-10 18:16:42 浏览: 34
这道题可以使用贪心算法求解。我们可以先将得分从大到小排序,然后依次给排名靠前的 $k$ 个人颁发证书。这样可以保证排名靠前的 $k$ 个人一定满意,而且对于一个得分最高的人,他一定可以拿到证书,因为他不会比其他人更不满意。
然后我们从第 $k+1$ 个人开始,依次检查他是否满意。如果他不满意,就给他颁发证书,这样可以保证他满意。但是可能会导致其他人不满意,所以我们需要检查其他人是否不满意,如果有,就再次颁发证书。具体实现时,我们可以使用一个数组记录每个人是否拿到了证书,初始时都为 false。然后依次遍历每个人,如果该人的得分比前面的人高,但是前面的人没有拿到证书,就将证书颁发给前面的人。如果该人的得分比后面的人低,但是后面的人已经拿到了证书,就将证书颁发给该人。然后再次遍历所有人,如果发现某个人不满意且还没有拿到证书,就给他颁发证书,并将其他人的状态重置。
以下是一份使用 C++ 实现的代码,时间复杂度为 $O(n^2)$,可以通过此题:
```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a.rbegin(), a.rend()); // 从大到小排序
vector<bool> has_cert(n, false); // 初始时都没有证书
for (int i = 0; i < k; i++) {
has_cert[i] = true; // 颁发给排名靠前的 k 个人证书
}
int ans = k;
bool flag = true;
while (flag) {
flag = false;
for (int i = k; i < n; i++) {
if (!has_cert[i]) { // 如果该人还没有拿到证书
bool satisfied = true;
for (int j = 0; j < i; j++) {
if (a[i] > a[j] && !has_cert[j]) { // 检查前面的人是否满意
satisfied = false;
break;
}
}
if (satisfied) { // 如果该人满意
has_cert[i] = true; // 颁发证书
ans++;
flag = true;
break;
}
satisfied = true;
for (int j = i+1; j < n; j++) {
if (a[i] < a[j] && has_cert[j]) { // 检查后面的人是否满意
satisfied = false;
break;
}
}
if (satisfied) { // 如果该人满意
has_cert[i] = true; // 颁发证书
ans++;
flag = true;
break;
}
}
}
if (flag) { // 如果有人拿到了证书,需要重置其他人的状态
for (int i = 0; i < n; i++) {
if (!has_cert[i]) {
bool satisfied = true;
for (int j = 0; j < n; j++) {
if (a[i] > a[j] && !has_cert[j]) { // 检查前面的人是否满意
satisfied = false;
break;
}
}
if (satisfied) { // 如果该人满意
has_cert[i] = true; // 颁发证书
ans++;
}
}
}
}
}
cout << ans << endl;
return 0;
}
```
该程序使用了一个名为 `has_cert` 的数组记录每个人是否拿到了证书,初始时都为 false。首先给排名靠前的 $k$ 个人颁发证书,然后依次遍历每个人,检查他是否满意,如果不满意,就给他颁发证书,并检查其他人是否不满意,重复这个过程直到没有人不满意为止。
希望这个代码对您有所帮助。