1 条题解
-
0
题解:实验安排问题
题目分析
我们有 个实验,重要度分别为 ,显然编号越小的实验重要度越高。
有 轮宇宙射线,在完成 个实验后发生,每轮会按照给定的脆弱度排列,干扰当前未完成且未被干扰的实验中最脆弱的一个。
目标:安排实验顺序,使得最终完成的 个实验的重要度总和最大。
关键观察
-
重要度性质:由于 随 增大而指数下降, 号实验的重要度 比 号以后的实验重要度总和还大。因此要尽量保留编号小的实验。
-
射线干扰规则:在第 轮射线时,系统会从当前所有未完成且未被干扰的实验中选择在排列 中最靠前的一个进行干扰。
-
策略核心:我们可以通过合理安排已完成实验的顺序,来"诱导"射线干扰我们不重要的实验,从而保护重要实验。
贪心思路
从后往前考虑时间线(逆序贪心):
设最终要保留的实验集合为 (),我们需要确定 中实验的执行顺序。
步骤:
-
确定要保留的实验:
- 由于重要度指数衰减,我们肯定希望保留编号 的实验。
- 但射线可能会强制干扰掉其中一些,所以我们需要调整策略。
-
逆序处理射线:
- 从最后一轮射线(第 轮)开始考虑,此时已经完成了 个实验。
- 在这一轮,系统会从所有未完成的实验中选出在 里最靠前的一个干扰。
- 为了保留重要实验,我们应该让这一轮干扰掉 中在未完成实验里最靠前、且在我们希望保留的集合中相对最不重要的那个。
-
具体算法:
- 初始化所有实验为"未完成"状态。
- 对于第 轮射线:
- 设当前已确定要做的实验集合为 (初始为空)
- 在所有实验中,找到在 里最靠前、且不在 中的实验 ,这个 就是第 轮会被干扰的实验
- 那么 不能出现在最终方案中
- 最终剩下的 个实验就是我们要做的
-
确定顺序:
- 现在知道了要做哪些实验,需要安排顺序使得每轮射线确实干扰我们预设的实验
- 可以这样构造:在射线轮次之前,确保被干扰的实验还没有做,并且其他重要实验尽量提前做
算法实现
更简洁的实现方法:
- 用布尔数组标记每个实验是否被干扰
- 逆序处理每轮射线:
- 扫描 ,找到第一个未被干扰且不在已安排实验中的实验,标记为被干扰
- 剩下的 个实验按任意顺序输出(实际上按编号从小到大输出就能保证重要度最大)
样例验证
样例 2:
3 1 1 2 3 1
- 第 1 轮射线:在 中找第一个,选 2 干扰
- 剩下实验 {1,3},输出顺序可以任意,如
1 3
或3 1
,但题目输出2 1
说明他们用了另一种构造方法
实际上,我们只要保证被干扰的是 2 和 3 中的一个,且最终包含 1 即可。
复杂度分析
- 每轮射线需要 时间找到被干扰的实验
- 总复杂度 ,在 时完全可行
代码框架
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n, m; cin >> n >> m; vector<int> a(m); for (int i = 0; i < m; i++) cin >> a[i]; vector<vector<int>> p(m, vector<int>(n)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { cin >> p[i][j]; } } vector<bool> interfered(n + 1, false); vector<bool> in_answer(n + 1, true); // 逆序处理每轮射线 for (int j = m - 1; j >= 0; j--) { // 找到这轮被干扰的实验 int target = -1; for (int x : p[j]) { if (!interfered[x] && in_answer[x]) { target = x; break; } } interfered[target] = true; in_answer[target] = false; } // 输出答案 vector<int> ans; for (int i = 1; i <= n; i++) { if (in_answer[i]) ans.push_back(i); } for (int i = 0; i < ans.size(); i++) { cout << ans[i] << " \n"[i == ans.size() - 1]; } return 0; }
总结
本题的关键在于:
- 认识到重要度的指数衰减性质,优先保护小编号实验
- 逆序处理射线,确定每轮被干扰的实验
- 最终保留的实验集合确定后,顺序可以相对自由安排
这是一个典型的贪心+逆序构造问题。
-
- 1
信息
- ID
- 3298
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者