题解:
这题主要是简单模拟,注意细节即可。
/*
问题:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=146
类型:简单模拟
时间: 2020年3月2日
*/
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <sstream>
using namespace std;
// 一些变量
struct PROCESS{
string code[30]; // 程序语句
int pc; // 程序指针
int num; // 语句总数
};
map<string, int> VAR; // var
vector<PROCESS> data;
deque<int> q_active,q_suspend; // 就绪队列与挂起队列,因为从挂起队列取出的程序需要放到就绪队列头部,所以用双端队列比较好
int n, t1, t2, t3, t4, t5, Q;
int lock; // 当前是否上锁? 用整数型方便记录发起上锁的进程(不过好像可以不记录,应该不会有一个程序连续lock,这样不合理
// 函数开始
void run(PROCESS &pro, int pid){
int time=Q;
while(time>0){
string code = pro.code[pro.pc];
if(code.find("=") != string::npos){
// 处理变量语句
int varValue;
string varName = code.substr(0,1);
stringstream temp; // 以下3行代码都是string转整数,也可以用atoi
temp<<code.replace(0,4,"");
temp>>varValue;
VAR[varName]=varValue;
pro.pc++;
time-=t1;
}
else if(code.find("print") != string::npos){
// 处理输出语句
cout << pid+1<< ": "<<VAR[code.replace(0,6,"")]<<endl;
pro.pc++;
time-=t2;
}
else if(code.find("unlock") != string::npos){
// 处理解锁语句
lock = 0;
if(!q_suspend.empty()){ // 注意,只取出一个,因为资源只能给一个程序
q_active.push_front(q_suspend.front()); // 送到活跃队列的头部,因为它等待的临界资源被释放了(unlock)
q_suspend.pop_front();
}
pro.pc++;
time-=t4;
}
else if(code.find("lock") != string::npos){
// 处理上锁语句
if(lock && lock!=pid+1){
q_suspend.push_back(pid);
return;
}
lock = pid+1;
pro.pc++;
time-=t3;
}
else{
// 处理结束语句
return;
}
}
q_active.push_back(pid); // 送入活跃(或者说就绪)进程队列的队尾
}
void fun(){
for(int i = 0; i < n; i++){ // 初始将所有进程加入就绪队列
q_active.push_back(i);
}
while(!q_active.empty()){
int pid = q_active.front(); // 取出进程id
q_active.pop_front();
run(data[pid], pid); // 执行进程
}
}
//#define debug
int main(){
#ifdef debug
freopen("input.txt", "r", stdin);
#endif
int N;
cin>>N; // 多组数据
while(N--){
lock = 0;
data.clear(); VAR.clear(); q_active.clear(); q_suspend.clear(); //一些数据的清除工作
cin>>n>>t1>>t2>>t3>>t4>>t5>>Q; // 接受程序数量、时间片等变量
char temp;scanf("%c", &temp); // 处理getline接收之前换行符的bug
for(int i = 0; i < n; i++){ // 接收n个程序的代码
PROCESS P;
P.pc=0;
P.num=0;
string c;
while(1){ // 开始构建程序
getline(cin,c); // 处理一行的数据,避免cin本身不接受空格的问题!
//P.code.push_back(c);
P.code[P.num]=c;
P.num++;
if(c == "end"){ // 接收完毕,送入data数组并跳出本次while
data.push_back(P);
break;
}
}
}
fun(); // 执行程序
if(N)cout<<endl; // 题面要求每组数据的输出之间需要一行空行
}
return 0;
}
/* 主要错误:
1.原先为了减少耦合和精神负担,将代码分在多个函数中,可能存在某些返回值不当的情况,故应当尽量减少函数之间的返回值传递
2.对于字符串匹配的问题,应当注意子串包含的问题
3.注意题意描述,unlock操作后只取出一个在挂起状态的进程。此外,注意相关时间片问题
4.在原getTime函数当中出现了子串包含问题,但没有发现,导致一直错误!
5.注意每个程序代码行数可能会超过25行,所以数组开到25以上或者用vector比较好!
6.这题为了降低难度,该题每个代码语句具有原子性
7.注意一共有N组数据,每组数据有多个程序
*/