UVA - 210 Concurrency Simulator

/*
  本题借鉴了LRJ在github上放的入门经典的代码库
  
  收获 && 总结:
  1. 双端队列deque
  下面这个博客总结的比较细致
  
  2. fgets函数
  http://www.cnblogs.com/aexin/p/3908003.html
  
  3. 该题最好不要用C++的getline,也不要用string,最好还是用字符串数组 char[][],因为我一开始用它们两时,尽管和LRJ的思路基本一样,还是被判Runtime Error,改了以后又是各种WA,后来改了许久才改对...对于输入格式的处理,还是用fgets比较好(虽然我暂时没有足够的理论依据支持这点)
*/


//一开始我是用C++写的,但是bug一直找不出来,只能先换C来写一次
#include <iostream>
#include <queue>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;

const int maxn = 1e3;
deque<int> ready;
queue<int> block;
int n, quantum, c[5], var[26], ip[maxn];
bool locked;
char code[maxn][20];
//ip[pid] 保存pid程序当前需执行的第一条代码,在code中的下标。最初是记录没个程序第一行代码的位置,带程序开始运行语句以后,没运行一句代码,对应程序的pid++ 
//所有程序存在code数组 

void run(int pid)
{
	int q = quantum;
	while (q > 0)
	{
		char*p = code[ip[pid]];
		switch (p[2])
		{
			case '='://赋值,因为常量给定小于100,只要判断其是否为两位,一位和两位的情况,分开处理即可,用 isdigit函数可简化代码 
			var[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0';
			q -= c[0];
			break;
			
			case 'i': //print
			cout << pid + 1 << ": " << var[p[6] - 'a'] << endl;
			q -= c[1];
			break;
			
			case 'c': //lock
			if (locked) 
			{
				block.push(pid); return;
			}
			locked = true;
			q -= c[2];
			break;
			
			case 'l': //unlock
			locked = false;
			if (!block.empty())
			{
				int pid2 = block.front();
				block.pop();
				ready.push_front(pid2);
			}
			q -= c[3];
			break;
			case 'd': //end
				return;
		}
		ip[pid]++;
	}
	ready.push_back(pid); //如果程序没有读完,重新进入等待队列,作为队尾 
}


int main()
{	
	int t;
	cin >> t;
	while(t--)
	{
		cin >> n;  rep(i, 5) cin >> c[i]; cin >> quantum;
		getchar();
		memset(var, 0, sizeof(var));
		
		int line = 0;
		rep(i, n) //先将n个程序的所有代码读入,保存到code 
		{ 
			fgets(code[line++], maxn, stdin);
			ip[i] = line - 1; 
			while (code[line - 1][2] != 'd')//不断读取代码,直到读完每组的end 
			fgets(code[line++], maxn, stdin);
	
			ready.push_back(i); //将这个程序压入等待队列			
		}
		locked = false;
		while (!ready.empty())
		{
			int tp = ready.front();
			ready.pop_front();
			run(tp);
		}
		if (t) cout << endl;
	}
	return 0;
}


//后来实在不甘心自己写的C++版本,一直有个bug找不出来,于是用udebug上的两组数据不断比对,调试、加输出,把可能有错的地方轮流换着修改,最后终于用C++写出了AC代码
//fgets换为getline以后,就一直出错!!!(hhh,这句好像是我昨天一直RE或者WA时,十分怨念,写下的注释)
#include <iostream>
#include <queue>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <fstream>
#define rep(i, n) for (int i = 0; i < (n); i++)
//#define debug
using namespace std;

const int maxn = 1e3;
deque<int> ready;
queue<int> block;
int n, quantum, c[5], var[26], ip[maxn];
bool locked;
string code[maxn];
//ip[pid] 保存pid程序当前需执行的第一条代码,在code中的下标。最初是记录没个程序第一行代码的位置,带程序开始运行语句以后,没运行一句代码,对应程序的pid++ 
//所有程序存在code数组 

void run(int pid)
{
	int q = quantum;
	while (q > 0)
	{
		string p = code[ip[pid]];
		switch (p[2])
		{
			case '=': //赋值,因为常量给定小于100,只要判断其是否为两位,一位和两位的情况,分开处理即可,用 isdigit函数可简化代码 
			var[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0';
			q -= c[0];
			break;
			
			case 'i': //print
			cout << pid + 1 << ": " << var[p[6] - 'a'] << endl;
			q -= c[1];
			break;
			
			case 'c': //lock
			if (locked) 
			{
				block.push(pid); return;
			}
			locked = true;
			q -= c[2];
			break;
			
			case 'l': //unlock
			locked = false;
			if (!block.empty())
			{
				int pid2 = block.front();
				block.pop();
				ready.push_front(pid2);
			}
			q -= c[3];
			break;
			case 'd': //end
				return;
		}
		ip[pid]++;
	}
	ready.push_back(pid); //如果程序没有读完,重新进入等待队列,作为队尾 
}

int main()
{
	#ifdef debug
	freopen("E:\\in.txt", "r", stdin);
	freopen("E:\\out.txt", "w", stdout);
	#endif
	cin.tie(0);
	cin.sync_with_stdio(false);
	int t;
	cin >> t;
	string temp;
	while (t--)
	{
	//	getline(cin, temp);
		cin >> n;  rep(i, 5) cin >> c[i]; cin >> quantum;
		getline(cin, temp);
	//	getchar();
		memset(var, 0, sizeof(var));
		
		int line = 0;
		rep(i, n) //先将n个程序的所有代码读入,保存到code 
		{ 
			getline(cin, code[line++]);
		//	cout << "test: " << code[line - 1] << endl;;
			ip[i] = line - 1; 
			while (code[line - 1] != "end") //不断读取代码,直到读完每组的end 
			{
				getline(cin, code[line++]);
		//		cout << "test: " << code[line - 1] << endl;
			}
			
			ready.push_back(i); //将这个程序压入等待队列 			
		}
		
		locked = false;
		while (!ready.empty())
		{
			int tp = ready.front();
			ready.pop_front();
			run(tp);
		}
		if (t) cout << endl;
	}
	#ifdef debug
	fclose(stdin);
	fclose(stdout);
	#endif
	return 0;
}


posted @ 2017-09-23 19:45  mofushaohua  阅读(326)  评论(0编辑  收藏  举报