题解 | #[HNOI2003]操作系统#

[HNOI2003]操作系统

https://ac.nowcoder.com/acm/problem/20030

#include<iostream>
#include<queue>
using namespace std;

struct mode {
	int name;
	int beg;
	int time;
	int value;
}jc;

bool operator<(const mode &a, const mode &b) {
    if(a.value==b.value)return a.name>b.name;
	return a.value < b.value;
}

int main() {
	int now = 0, deadline = 0;
	priority_queue<struct mode>pq;
	cin >> jc.name >> jc.beg >> jc.time >> jc.value;
	pq.push(jc);
	now = jc.beg;
	while (cin >> jc.name >> jc.beg >> jc.time >> jc.value) {
		deadline = jc.beg;
		while (now < deadline) {
			if (pq.empty()) {
				now = deadline;
				break;
			}
			else if (now + pq.top().time <= deadline) {
				now += pq.top().time;
				cout << pq.top().name << " " << now << endl;
				pq.pop();
			}
			else {
				struct mode shadow = pq.top();
				shadow.time -= (deadline - now);
				now = deadline;
				pq.pop();
				pq.push(shadow);
			}
		}
        pq.push(jc);
	}
    while(!pq.empty()){
        cout << pq.top().name << " " << now + pq.top().time<<endl;
        now+=pq.top().time;
        pq.pop();
    }
}


这道题分类比较麻烦而且容易错,不好打断点但是可以在不同分支中打唯一标记输出来微调(忽视这句话)。这题我的具体做法是先塞一个进程进队列,然后设置一个deadline为下一个进来的进程到达的时间(为什么选择以这个作为时间点,原因是我们并不知道队列中的top优先级是否高于进来的新进程,那么对于每一个时间段来说要执行哪个进程就成了问题,诚然可以全读入再对整体处理,但那样不仅处理极其繁琐并且没有利用到数据按照进程到来顺序给定这个条件会扩大复杂度,虽然这题数据很水基本不会爆爆爆),now作为当前执行到的时间点(因为要求输出的是进程名和结束时间,如果直接用时间线上的点来表示利于我们中断退出而且不容易出错,涉及数据少容易调试),now随着时间的推进要与时俱进地更新,时间是否推进是根据每一段时间的归属决定的,时间判断出归属某个进程以后,最后要记得更新now。,这样对于执行情况来说会有两种,一种是当前队列中的优先级top进程能在下一个进程到达之前直接跑完,那么我们就直接让它跑完,输出它然后让它退出;一种则是进程的所需执行时间比较长,在下一个进程到达前跑不完,所以我们考虑到一个问题如何记录下没跑完的情况呢?没错就是利用执行时间time属性,在我的设计中它也有剩余所需执行时间的含义,我们让time减去对应这段的时间来更新time值就行了(这里需要提一下可以看到我用了一个结构体shadow来复制了队列的最高优先级进程top,因为这道题涉及到结构体进入优先队列的比较规则问题,我重载了比较规则operator,考虑到优先级越高的自然越前,但同时存在优先级相同的情况,所以需要单独写一条如果优先级相同按照进程名字保持原顺序不变(这是因为这道题数据很水,测试数据的进程名都是升序排列的,其实但凡给你的进程号有一个前面大于后面的hack数据直接爆炸。更精密一点的写法是给每个进程按照进来的顺序额外上一个升序编号,按照这个编号来排列而不是name排列就不会有这样的隐患,我因为懒这里没有弄,估计所有测试数据里进程号升序给你单纯是出题人的仁慈)。结构体里面的各元素可以看到传参是const修饰引用类型的,所以不能直接改变他们里面的数值,必须复制一份,在队列外才能更新time属性值,再从队列中删除top进程,最后用我们的复制品shadow加入队列完成替换),当time成0时代表一个进程剩余的所需执行时间没了也就是它跑完了的意思,那自然可以输出他然后让他退出。想到这里还没完,因为now还没到deadline,即下个进程还没到来,如果队列中还存在进程,那么也是需要继续进行的(具体怎么进行的和上面一样,所以能看到我程序里用了一个while(now<deadline),这是循环判断的意思),如果队列中进程全跑完了一个没有了那么直接把now拉到下个进程jc到来的时间点deadline退出循环。然后让jc进队(因为jc在新循环马上要接收新的值了,无论前面的进程跑完了没,jc已经到了,自然要进队,至于优先级,优先队列会按照我们重载后的比较规则自己排列维护的,我们不用管这些细节)。这样还没完,最后可能存在所有程序都到了但是进程队列中因为种种原因滞留进程导致进程数量事实上不一定为1而是>=1,所以需要写一个循环while(!pq.empty())来切掉所有剩下的进程,这里的处理就会相对比较简单,因为没有新的进程会加进来的,所以只需要按照优先队列的顺序,挨个跑完top进程每一步都更新now输出就行了。

全部评论

相关推荐

头像
01-22 10:36
已编辑
牛客运营
活动规则:你可以使用任何AI工具,生成牛客娘表情包,发送你的生成提示词+图片至本贴评论区,并将无水印原图发送至微信群。活动奖励:1、每张&nbsp;可爱的牛客娘表情包,可获得&nbsp;10牛币奖励(每人上限100张)&nbsp;~2、点赞量最高的前xx个评论,送牛客娘马克杯,(每25个评论,赠送一个马克杯,最多赠送20个)牛客娘表情包交流群:生成示例:&nbsp;这是牛客娘的形象,帮我用牛客娘的形象画一些ACM算法竞赛相关的表情包&nbsp;需要的表情包有:&nbsp;摸头&nbsp;(安慰)&nbsp;呵呵(冷笑的呵呵)&nbsp;牛魔&nbsp;牛啤(左手比大拇指,右手拿着啤酒)&nbsp;这次一定&nbsp;比心&nbsp;不许TD&nbsp;要给他迎头痛击&nbsp;设计要求:&nbsp;1.统一使用萌系风格。&nbsp;2.表情生动和肢体动作丰富、...
Xuan2333:没错没错就是我,牛客娘表情包的创作者,大家都可以自用哒awa (第5张“按住牛客娘开始思索”出自我的世界里的机械动力模组,我做这个表情包可是花了我1个多小时的时间啊qwq) 最后附上所有用过的素材图,希望大家喜欢awa wow 将图片中的人物改成两手托腮,只显示头部照片,眼睛为星星眼,表情开心,并在下方附上文字“wow” Ciallo 将第二张图的人物做出第一张图的姿势并且要在身体各处还有五官和动作完全一致,不要改背景,高分辨率,最佳质量,并在下方加上和图片相符的文字“Ciallo!” 说不出话 生成这个任务面无表情,一脸犹豫,嘴角下垂,双手交叉在胸前,在中间加上一个带有一条斜杠的麦克风的表示闭麦的符号,并且在下面配上文字“说不出话” 按住牛客娘开始思索 将第二张图的人物进行修改,要求是有一只手按在人物的头上,人物的眼神灵动,手略有着急的轻微摆起,头部微微抬起,并将第一张图放在第二张图的下方,高品质,把这张图的下方的黑色部分加上文字“按住牛客娘开始思索”,字体与图片里展示的“牛客娘”这三个字的字体相一致 我也要WA吗 将第一张图的人物的头发,脸部和衣服改成第二张图的人物的,眼睛保持不变,脸上的汗保持不变,头发的长度修改为和图片的一致,脸上不要有红晕,眼睛里不要有高光,眼睛里只要纯灰色查看图片
点赞 评论 收藏
分享
2025-12-26 10:52
河北传媒学院 Java
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务