并行程序模拟(Concurrency Simulator,ACM/ICPC World Finals 1991,UVa 210)

并行程序模拟

问题描述

你的任务是模拟n个程序(按输入顺序编号为1~n)的并行执行。每个程序包含不超过25条语句,格式一共有5种:
var=constant(赋值);print var(打印);lock;unlock;end。
变量用单个小写字母表示,初始为0,为所有程序公有(因此在一个程序里对某个变量赋值可能会影响另一个程序)。常数是小于100的非负整数。
每个时刻只能有一个程序处于运行态,其他程序均处于等待态。上述5种语句分别需要t1、t2、t3、t4、t5单位时间。运行态的程序每次最多运行Q个单位时间(称为配额)。当一个程序的配额用完之后,把当前语句(如果存在)执行完之后该程序被插入一个等待队列中,然后处理器从队首取出一个程序继续执行。初始等待队列包含按输入顺序排列的各个程序,但由于lock/unlock语句的出现,这个顺序可能会改变。
lock的作用是申请对所有变量的独占访问。lock和unlock总是成对出现,并且不会嵌套。lock总是在unlock的前面。当一个程序成功执行完lock指令之后,其他程序一旦试图执行lock指令,就会马上被放到一个所谓的阻止队列的尾部(没有用完的配额就浪费了)。当unlock执行完毕后,阻止队列的第一个程序进入等待队列的首部。
输入n,t1,t2,t3,t4,t5,Q以及n个程序,按照时间顺序输出所有print语句的程序编号和结果。

样例输入

3 1 1 1 1 1 1
a=4
print a
lock
b=9
print b
unlock
print b
end
a=3
print a
lock
b=8
print b
unlock
print b
end
b=5
a=17
print a
print b
lock
b=21
print b
unlock
print b
end

样例输出

1:3
2:3
3:17
3:9
1:9
1:9
2:8
2:8
3:21
3:21

题解:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<deque>
#define maxn 30
using namespace std;
int num,t[5],q,var[maxn];
char program[maxn][maxn][maxn];
int value(char *integer){
	int i=0,outcome=0;
	while(integer[i]!='\0'){
		outcome*=10;//字符型数字
		outcome+=integer[i++]-'0';//依次将字符型数字转化成整型数字
	}
	return outcome;
}
void solution(){
	deque<int> dd,zz;//双端队列
	for(int i=0;i<num;i++)
		dd.push_back(i);//等待队列的尾部插入程序的编号
	memset(var,0,sizeof(var));//全部变量赋值为0
	int play[maxn]={0},flag=0;// 状态参量,play为pc指针,flag为是否搜定
	while(!dd.empty()){//判断队列是否为空
		int cx=dd.front(),r=q,finished=0;//q是配额时间,cx为等待队列的第一个元素
		dd.pop_front();//等待队列 删除头部第一个元素
		while(r>0&&!finished){//配额单位时间大于0并且finished等于0
			char c=program[cx][play[cx]][0];//将三维数组中的程序语句赋值给c
			if(program[cx][play[cx]][1]!='=')//如果下一个字符不是等于号
				switch(c){//判断第一个字符是什么
				case 'p'://print
					printf("%d: %d\n",cx+1,var[program[cx][play[cx]][5]-'a']);
					r-=t[1];//配额时间减去语句所耗时间
					play[cx]++;//该程序将执行下一条语句
					break;
				case 'l'://lock
					if(flag){//flag不为0
						zz.push_back(cx);//阻止队列尾部添加cx
						r=-10000000;//特殊值用于后面是否入队判断,注意和正常可能取值区分,-1也是正常的
					}
					else{
						flag=1;//改变flag的状态
						r-=t[2];//减去语句二的时间
						play[cx]++;
					}
					break;
				case 'u'://unlock
					flag=0;//改变flag的状态
					if(!zz.empty()){//查看阻止队列是否为空,如果不为空
						int p=zz.front();//p为阻止队列头部第一个元素
						zz.pop_front();//删除阻止队列的头部第一个元素
						dd.push_front(p);//将p放到等待队列的头部
					}
					r-=t[3];//配额时间减去语句所消耗的时间
					play[cx]++;
					break;
				case 'e':
					r=0;//配额时间为0
					finished=1;//改变finished的状态,不再进入循环
					break;
			}
			else{//如果下一个字符是等号
				var[c-'a']=value(program[cx][play[cx]]+2);//进行赋值
				r-=t[0];//配额时间减去语句所耗时间
				play[cx]++;
			}
		}
		if(!finished&&r!=-10000000)//如果finished为0并且没有lock
			dd.push_back(cx);//等待队列尾部加上cx
	}
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&num);//输入num,表示程序的个数
		for(int i=0;i<5;i++)
			scanf("%d",&t[i]);//输入五种语句所需的单位时间
		scanf("%d",&q);//输入配额
		getchar();
		for(int i=0;i<num;i++){
			char cxyj[maxn];//temp字符数组存储程序语句
			int j=0;
			while(1){
				char c;
				int k=0;
				while((c=getchar())!='\n')//当输入的不是回车时
					cxyj[k++]=c;//输入程序语句
				cxyj[k]='\0';//字符数组最后加上'\0'
				if(strcmp(cxyj,"end")==0){//如果遇到end
					strcpy(program[i][j],cxyj);//将程序语句复制到program中
					break;//跳出循环
				}
				int ii=-1,jj=0;
				while(cxyj[++ii]!='\0')
					if(cxyj[ii]!=' ')//将空格剔除,将非空格字符录入数组
						program[i][j][jj++]=cxyj[ii];//将程序语句录入program数组
				program[i][j][jj]='\0';
				j++;
			}
		}
		solution();
		if(T)
			puts("");
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值