并行程序模拟
问题描述
你的任务是模拟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("");
}
}