UVA-210 Concurrency Simulator

UVA-210 Concurrency Simulator

题意:

让你模拟并行程序。程序可以执行以下五种操作:

操作 耗时 作用
\(variable = constant\) \(c_1\) 将单字母变量(\(variable\))赋值为\(constant\)
\(print\ constant\) \(c_2\) 将变量\(varable\)的值打印出来
\(lock\) \(c_3\) 将所有变量上锁,在\(unlock\)之前任何程序都不能对变量进行修改。
\(unlock\) \(c_4\) 解锁变量
\(end\) \(c_5\) 程序结束

每个程序按照输入的先后依次放入主程序队列执行。运行程序时,每个程序每次只会被分配\(Q\)这么长时间,也就是说当这个程序单次运行的总时间超过\(Q\)这么久之后,它在执行完当前命令之后就会被放到主程序队列的队尾等待下一次的执行。

注意到上面的\(lock\)\(unlock\),在\(lock\)状态下任何想要再次执行\(lock\)的程序都会被放入\(blocked\ queue\)的尾部。当\(unluck\)执行之后,他首先会解锁,之后如果\(block\ queue\)不为空,那么就会把\(block\ queue\)队首程序放入主程序队列的队首。

让你输入每个\(print\)的程序编号以及\(print\)的结果。


思路:

思路参考了lrj大佬的代码。

将命令存储在单独的数组中,将每个程序的第一条命令的位置存储在\(ip\)数组中,之后每执行完一次命令之后就将程序对应的\(ip+1\),也就是移动到下一条命令的位置。当移动到\(end\)的时候就不再移动了。

不得不佩服lrj大佬的代码美如画,代码逻辑清晰,变量名称得当 tql。


AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cctype>

const int Maxn = 1000;

std::deque<int>readyQ;
std::queue<int>blockQ;

int n, q, c[5], ip[Maxn], var[30];
char program[Maxn][Maxn];
bool locked;

void init() {
	locked = false;
	memset(program, 0, sizeof program);
	memset(var, 0, sizeof var);
	for (; !readyQ.empty(); readyQ.pop_front());
	for (; !blockQ.empty(); blockQ.pop());
}

void run(int pid) {
	int rq = q;
	while (rq > 0) {
		char *p = program[ip[pid]];
		switch (p[2]) {
			case '=': // assignment
				var[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0';
				rq -= c[0];
				break;
			case 'i': // print
				printf("%d: %d\n", pid + 1, var[p[6] - 'a']);
				rq -= c[1];
				break;
			case 'c': // lock
				if (locked) {
					blockQ.push(pid);
					return;
				}
				locked = true;
				rq -= c[2];
				break;
			case 'l': // unlick
				locked = false;
				if (!blockQ.empty()) {
					int fp = blockQ.front();
					blockQ.pop();
					readyQ.push_front(fp);
				}
				rq -= c[3];
				break;
			case 'd': // end
				return;
		}
		ip[pid]++;
		/* 这里在未遇到end之前,也就是程序结束之前正常+1;遇到end直接return这里会一直保持在end的状态 */
    /* 同理在lock状态下再次lock */
	}
	readyQ.push_back(pid);
	/* return之后程序就不会再次入队了 */
}

void solve() {
	init();
	scanf("%d", &n);
	for (int i = 0; i < 5; i++) {
		scanf("%d", c + i);
	}
	scanf("%d", &q);
	int t = 0;
	for (int i = 0; i < n; i++) {
		fgets(program[t++], Maxn, stdin);
		ip[i] = t - 1;
		while (program[t - 1][2] != 'd') {
			fgets(program[t++], Maxn, stdin);
		}
		readyQ.push_back(i);
	}
	for (; !readyQ.empty(); ) {
		int pid = readyQ.front();
		readyQ.pop_front();
		run(pid);
	}
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2021-02-04 12:59  牟翔宇  阅读(65)  评论(0编辑  收藏  举报