题记
这道题最关键就是要发现每次配对都是发生在每个进程的最开始,还有一点比较绕的是每个进程必须完全执行完一次才能进入下一次任务,但是对方进程不一定马上回应,可以执行完另一个任务再响应,但是总的来说配对还是发生在最开头。比如有三个进程a,b,c。a发一个任务等b回应,b第一个任务是和c进行交互,完成后b第一个就变成了对a的回应。所以每次对各个进程第一个取出来,看看它们之间是否存在可以配对的,如果没有,说明存在死锁或者所有任务都完成了。
#include <iostream>
#include <string>
#include <queue>
#include <sstream>
using namespace std;
const int Maxn=1e4+10;
//输入
int T,n;
struct node {
int type;//R-0,S-1
int need;//需要need号进程回应
};
queue<node> q[Maxn];
int findnum(string& str){
int n=str.size(),ans=0;
for(int i=1;i<n;i++)
ans=ans*10+str[i]-'0';
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>T>>n;
cin.get();//吃掉换行符
while(T--){
for(int i=0;i<n;i++){
string line;
string command;
getline(cin,line);
stringstream ss(line);
while(ss>>command){
node temp;
temp.type=command[0]-'R';
temp.need=findnum(command);
q[i].push(temp);
}
}
int cnt;
bool flag=true;
while(1){
//对每一个进程的第一个遍历看看有没有配对的
cnt=0;//遍历一趟成功配对数.遍历完还是0一定有死锁
for(int i=0;i<n;i++){
if(q[i].empty())//这个进程的命令执行完了,接着下一个
continue;
node u=q[i].front();
if(q[u.need].empty()){//需要回应的进程已经空了,一定有死锁
flag=false;
break;
}
else{
node v=q[u.need].front();
if(v.type^u.type&&v.need==i){
q[i].pop();
q[u.need].pop();
i--,cnt++;//i号进程配对成功一个,接着对i号配对.紧着一个进程做
}
else
continue;
}
}
if(!flag||!cnt)
break;
}
for(int i=0;i<n;i++)
if(!q[i].empty()){
flag=false;
cout<<"1"<<endl;
break;
}
if(flag)
cout<<"0"<<endl;
for(int i=0;i<n;i++)
q[i]=queue<node>();//清空每个队列
}
return 0;
}
样例输入1
3 2
R1 S1
S0 R0
R1 S1
R0 S0
R1 R1 R1 R1 S1 S1 S1 S1
S0 S0 S0 S0 R0 R0 R0 R0
样例输入2
2 3
R1 S1
R2 S0 R0 S2
S1 R1
R1
R2 S0 R0
S1 R1