【CSP试题回顾】201709-2-公共钥匙盒(优化)

CSP-201709-2-公共钥匙盒

解题思路

这个问题描述了一个关于管理和还取钥匙的过程,在一个学校中,所有的教室钥匙都必须放在公共钥匙盒里,老师上课需要用到钥匙时,会从钥匙盒中取出,上完课后再将钥匙还回。题目要求根据给定的教师使用钥匙的时间安排,计算出最终钥匙盒内钥匙的顺序。

  1. 初始化钥匙盒:首先,根据钥匙的总数N,初始化钥匙盒,每个挂钩上挂的钥匙编号是从1到N的顺序。

  2. 读取和处理输入:接下来,根据老师的数量K,读取每位老师使用钥匙的编号、开始上课的时间以及上课的时长。对于每位老师,会有两个关键时间点:取钥匙的时间和还钥匙的时间。这两个时间点分别对应一个操作:取钥匙(operate=0)和还钥匙(operate=1)。每个操作都记录下来,包括操作的时间、类型(取或还)、以及钥匙编号。

  3. 排序操作:将所有的操作(包括取钥匙和还钥匙的操作)按时间顺序进行排序。如果两个操作发生在同一时间,还钥匙的操作优先于取钥匙的操作进行,如果还是相同,按钥匙编号顺序进行。这是因为题目规定如果同一时刻有老师还钥匙和取钥匙,应该先还后取。

  4. 执行操作:遍历排序后的操作列表,根据操作的类型(取或还),更新钥匙盒的状态。当老师取钥匙时,找到该钥匙并标记为已取出(例如,可以设置为-1表示钥匙不在盒子中)。当老师还钥匙时,找到最左边的空挂钩,将钥匙挂回。这里,空挂钩也是用-1表示。

  5. 输出结果:遍历钥匙盒,打印每个挂钩上的钥匙编号,这就是最终的钥匙排列顺序。

完整代码

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;

struct key
{
    int time;
    int operate; // 0-get 1-back
    int index;
};

bool cmp(key&a,key&b)
{ 
    if (a.time == b.time)
    {
        if (a.operate && (!b.operate)) // back A
            return true;
        else if ((!a.operate) && b.operate) // back B
            return false;
        else if (a.operate == b.operate)
            return a.index < b.index;
    }
    else
        return a.time < b.time;
}

int N, K, w, s, c;

int main()
{
    cin >> N >> K;
    vector<int> box(N); 
    for (size_t i = 0; i < N; i++)
    {
        box[i] = i + 1;
    }
    vector<key> opt(2 * K);
    for (size_t i = 0; i < K; i++)
    {
        cin >> w >> s >> c;
        opt.push_back({s, 0, w});
        opt.push_back({s + c, 1, w});
    }
    sort(opt.begin(), opt.end(), cmp);
    for (auto &it : opt)
    {
        if (it.operate) // back
        {
            for (auto &jt : box) 
            {
                if (jt == -1) 
                {
                    jt = it.index;
                    break;
                }
            }
        }
        else // get
        {
            for (auto &jt : box) 
            {
                if (jt == it.index) // find key
                {
                    jt = -1;
                    break;
                }
            }
        }
    }
    for (auto &it : box)
    {
        cout << it << " ";
    }
    return 0;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值