UVA210 - Concurrency Simulator

前言:

最近因为需要准备复试上机,所以又重新开始练一些算法题。
虽然之前没有记录解题思路或者代码的习惯,但是最近可能会经常发一些这类的文章。

题解:

这题主要是简单模拟,注意细节即可。

/*
	问题:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=146
	类型:简单模拟
	时间: 2020年3月2日 
*/ 

#include 
#include 
#include 
#include 
#include 
#include 
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组数据,每组数据有多个程序 
*/

你可能感兴趣的:(竞赛与认证)