您的位置:首页 > 理论基础 > 数据结构算法

【Jason's_ACM_解题报告】Concurrency Simulator

2015-02-14 22:34 387 查看

Concurrency Simulator 

Programs executed concurrently on a uniprocessor system appear to be executed at the same time, but in reality the single CPU alternates between the programs, executing some number of instructions from each program before switching to the next. You are to simulate
the concurrent execution of up to ten programs on such a system and determine the output that they will produce.

The program that is currently being executed is said to be running, while all programs awaiting execution are said to be ready. A program consists of a sequence of no more than 25 statements, one per line, followed by an end statement. The statements available
are listed below.


 


Each statement requires an integral number of time units to execute. The running program is permitted to continue executing instructions for a period of time called its quantum. When a program's time quantum expires, another ready program will be selected to
run. Any instruction currently being executed when the time quantum expires will be allowed to complete.

Programs are queued first-in-first-out for execution in a ready queue. The initial order of the ready queue corresponds to the original order of the programs in the input file. This order can change, however, as a result of the execution of lock and unlock
statements.

The lock and unlock statements are used whenever a program wishes to claim mutually exclusive access to the variables it is manipulating. These statements always occur in pairs, bracketing one or more other statements. A lock will always precede an unlock,
and these statements will never be nested. Once a program successfully executes a lock statement, no other program may successfully execute a lock statement until the locking program runs and executes the corresponding unlock statement. Should a running program
attempt to execute a lock while one is already in effect, this program will be placed at the end of the blocked queue. Programs blocked in this fashion lose any of their current time quantum remaining. When an unlock is executed, any program at the head of
the blocked queue is moved to the head of the ready queue. The first statement this program will execute when it runs will be the lock statement that previously failed. Note that it is up to the programs involved to enforce the mutual exclusion protocol through
correct usage of lock and unlock statements. (A renegade program with no lock/unlock pair could alter any variables it wished, despite the proper use of lock/unlock by the other programs.)

Input

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

The first line of the input file consists of seven integers separated by spaces. These integers specify (in order): the number of programs which follow, the unit execution times for each of the five statements (in the order given above), and the number of time
units comprising the time quantum. The remainder of the input consists of the programs, which are correctly formed from statements according to the rules described above.

All program statements begin in the first column of a line. Blanks appearing in a statement should be ignored. Associated with each program is an identification number based upon its location in the input data (the first program has ID = 1, the second has ID
= 2, etc.).

Output

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

Your output will contain of the output generated by the print statements as they occur during the simulation. When a print statement is executed, your program should display the program ID, a colon, a space, and the value of the selected variable. Output from
separate print statements should appear on separate lines.

A sample input and correct output are shown below.

Sample Input

1

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

Sample Output

1: 3

2: 3

3: 17

3: 9

1: 9

1: 9

2: 8

2: 8

3: 21

3: 21

这道题还是有一定的难度的,从一开始自己把它写出来,一直到调试通,一共花了一整天的时间。

对题目的理解我有还多偏差,导致了这道题的错误,但是本身的解决方案是正确的。

首先是我对题目的理解严重受Liu的影响,他说lock的作用是深情对所有变量的访问,但是事实上,原题只字未提,仅仅是作为对其他进程阻塞的一条指令,所以,可以对变量随时修改。

其次是假如一条指令正在执行时,该程序的时间片就用完了的话,需要等待指令执行完后才能退出。但是在这里我想当然的进行了特判,让其退出,这也是为什么我的程序一直TLE,Time Limit Exceeded 的原因。

由于我一直认为自己的做法是正确的,所以就以为是否是STL太慢了的原因,然后把string类改为了char类型读入。其实都是没有必要的。只需要将之前的特判改动一下就好了。

附代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
#include<deque>
#include<vector>
#include<string>

using namespace std;

#define MAXN (100000)

struct CMD{
int x,y;
};//x为操作行为编号,y为操作数。
//x 0-25:变量赋值,对应着a-z;此时y为常量;
//x 26:print操作;此时y为被操作变量;
//x 27:lock;此时y没有作用;
//x 28:unlock;此时y没有作用。
//x 29:end;此时y没有作用。

int var[26];//26个变量。
vector<CMD> pro[MAXN];//各个程序的指令。
int place[MAXN];//程序下次进入unit应该执行的指令。
bool islock;//变量是否被锁。
int who;//谁锁的
queue<int> block;//阻塞队列
deque<int> wait;//等待队列
int n,T;
int t[6];

void exe(int ID){
int tt=T;
while(tt>0){
int xx=pro[ID][place[ID]].x,yy=pro[ID][place[ID]].y;
if(0<=xx&&xx<=25){
var[xx]=yy;
tt-=t[1];
}else if(xx==26){
printf("%d: %d\n",ID+1,var[yy]);
tt-=t[2];
}else if(xx==27){
if(islock){
block.push(ID);
return ;
}
islock=true;
who=ID;
tt-=t[3];
}else if(xx==28){
islock=false;
if(!block.empty()){
wait.push_front(block.front());
block.pop();
}
tt-=t[4];
}else if(xx==29){
return ;
}
place[ID]++;
}
wait.push_back(ID);
}

void CLR(){
memset(var,0,sizeof(var));
memset(place,0,sizeof(place));
for(int i=0;i<n;i++)pro[i].clear();
islock=false;
who=-1;
while(!block.empty())block.pop();
wait.clear();
}

void read_pro(int ID){
char s[10];
for(int i=0;i<10;i++)s[i]=' ';
while(scanf("%s",s)){
if(s[2]=='d'){
pro[ID].push_back((CMD){29,0});
break;
}
else if(s[2]=='i'){
scanf("%s",s);
pro[ID].push_back((CMD){26,s[0]-'a'});
}
else if(s[2]=='c')pro[ID].push_back((CMD){27,0});
else if(s[2]=='l')pro[ID].push_back((CMD){28,0});
else{
int x=s[0]-'a';
scanf("%s",s);
int y;
scanf("%d",&y);
pro[ID].push_back((CMD){x,y});
}
for(int i=0;i<10;i++)s[i]=' ';
}
}

int m
9378
ain(){
//freopen("in.txt","r",stdin);
int total;
scanf("%d",&total);
while(total--){
CLR();
scanf("%d%d%d%d%d%d%d",&n,&t[1],&t[2],&t[3],&t[4],&t[5],&T);
for(int i=0;i<n;i++){
read_pro(i);
wait.push_back(i);
}
while(!wait.empty()){
int ID=wait.front();
wait.pop_front();
//cout<<ID<<endl;
exe(ID);
}
if(total)printf("\n");
}
//fclose(stdin);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息