CSP-201709-2-公共钥匙盒
关键点
1. 选择恰当的数据结构存储钥匙的存取操作
结构体MyKey
包含三个字段:time
、opt
和index
。
time
字段表示操作发生的时间点。对于取钥匙的操作,这个时间就是老师上课的开始时间;对于还钥匙的操作,这个时间是老师上课结束的时间(也就是开始时间加上持续时间)。opt
字段是一个布尔值,用于表示是取钥匙还是还钥匙。在我们的案例中,我们使用1来表示取钥匙,0来表示还钥匙。这个字段对于区分同一时间点发生的不同操作类型很重要。index
字段表示钥匙的编号,即它对应哪一把钥匙。
2. 按照题目描述的优先级大小排序
题目要求在处理钥匙存取操作时遵循一定的优先级顺序:首先按照操作的时间排序,如果时间相同,则取钥匙的操作应在还钥匙的操作之前处理,如果仍然相同,则按照钥匙的编号排序。
实现这个需求,我们使用自定义的比较函数myCmp
来为keyList
数组进行排序。这个比较函数遵循以下规则:
- 首先比较
time
字段。较早的时间应该排在前面。 - 如果
time
字段相等,则比较opt
字段。由于我们规定取钥匙(1)应该在还钥匙(0)之前,所以opt
较大的应该排在前面。 - 如果
opt
也相同,则比较index
字段,即钥匙编号,较小的编号排在前面。
这个排序规则确保了我们可以按照题目要求的顺序处理所有的钥匙存取操作。经过排序后,我们的算法将按照正确的时间顺序和优先级来模拟每一次钥匙的取还过程,从而准确地重现钥匙盒中钥匙的最终状态。
解题思路
-
输入处理:首先,代码从标准输入读取两个整数N和K,其中N表示钥匙总数(和挂钩的数量相同),K表示总共有多少个教师需要使用钥匙。然后,代码读取接下来的K行输入,每行包含三个整数w, s, c,分别代表一位老师使用的钥匙编号、上课开始的时间和上课的时长。
-
初始化钥匙盒状态:初始化一个名为
box
的整数向量,大小为N,代表钥匙盒的状态。初始状态下,钥匙是按照编号从小到大顺序排列的,即box[i] = i + 1
。 -
构造时间线:对于每一位老师,记录两个时间点:取钥匙的时间和还钥匙的时间。这是通过构造一个结构体数组
keyList
来实现的,每个结构体元素记录了时间点、操作类型(取还)和钥匙编号。其中,opt
字段用于区分是取钥匙(1)还是还钥匙(0)。 -
时间线排序:使用自定义的比较函数
myCmp
对keyList
进行排序。排序规则是:首先按时间点排序,如果时间点相同,则取钥匙的操作排在还钥匙的操作之后,如果还存在相同,则按钥匙编号进行排序。 -
模拟钥匙的取还过程:遍历排序后的时间线,根据操作类型更新钥匙盒
box
的状态。如果是还钥匙(opt
为0),找到box
中第一个空位置(用-1表示),并将相应的钥匙编号放在那里。如果是取钥匙(opt
为1),找到钥匙盒中对应的钥匙并将其位置设为-1,表示钥匙被取走。 -
输出最终钥匙盒状态:遍历
box
向量,输出每个挂钩上的钥匙编号。这就是最终的钥匙盒状态。
完整代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;struct MyKey
{int time; // 操作时间bool opt; // 0-还 1-取int index; // 钥匙序号
};bool myCmp(MyKey& a, MyKey& b) { // 优先级:操作时间 > 还/取 > 序号if (a.time == b.time) {if (a.opt == b.opt) return a.index < b.index;else{if (!a.opt) return true;else if (!b.opt) return false;}}return a.time < b.time;
}int N, K, w, s, c;
vector<MyKey>keyList;int main() {cin >> N >> K;vector<int>box(N);for (int i = 0; i < box.size(); i++){box[i] = i + 1;}for (int i = 0; i < K; i++){cin >> w >> s >> c;keyList.push_back({ s,1,w });keyList.push_back({ s + c,0,w });}sort(keyList.begin(), keyList.end(), myCmp);for (auto& it : keyList) {if (!it.opt) // 还钥匙{for (auto& jt : box) {if (jt == -1){jt = it.index;break;}}}else // 取钥匙{for (auto& jt : box) {if (it.index == jt){jt = -1;break;}}}}for (auto& it : box) {cout << it << " ";}return 0;
}
文章部分内容参考自:CSP:公共钥匙盒