一道模拟题
竟然活生生的不会模拟,感觉自己好菜啊。
在模拟的时候,一定要弄清楚要对什么进行模拟。
题解
进程的等待队列是一个优先队列,优先队列是以优先级降序作为第一关键字,以进入时间为第二关键字。
在操作系统这道题目中,我们依据任务到达来驱动我们对进程的执行模拟。
记录上个任务到来的时间为now,本次任务到来的时间为tim。
(即上次中断的时间和本次中断的时间,是进程能够执行的时间)
这样的话,本次任务到达的时候,我们必须把等待队列中的任务拿出来,在[now,tim)[now,tim)这段时间内执行。如果有执行完的任务,那么就输出,否则的话,把剩余时长减去本次运行的时长,然后再push回等待队列中去。
并且把本次的任务推入到等待队列中去。
这样一直模拟下去就ok了。
本质上来说,任务的到来相当于一次中断,迫使所有的任务重新加回到优先队列里面去,然后把刚到来的任务也一同加入到优先队列去,重新选择一个优先级更高的执行。
代码
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
#define pr(x) cout<<#x<<":"<<x<<endl
struct job{int pid,time,leng,prio;
};
struct cmp1{bool operator()(job jb1,job jb2){if(jb1.prio != jb2.prio) return jb1.prio < jb2.prio;else return jb1.time > jb2.time;}
};
int pid,tim,leng,prio,cnt,now,k;
int main(){priority_queue<job,vector<job>,cmp1> Q;while(k = scanf("%d%d%d%d",&pid,&tim,&leng,&prio)){if(k == EOF) tim = 1e9;job newjob = (job){pid,tim,leng,prio};while(!Q.empty() && now < tim){job tmp = Q.top();Q.pop();int use = min(tim-max(now,tmp.time),tmp.leng);tmp.leng -= use;now = max(now,tmp.time)+use;if(tmp.leng){Q.push(tmp);}else{printf("%d %d\n",tmp.pid,now);}}Q.push(newjob);if(k == EOF) break;}}