原文鏈接
原題鏈接
思路
主要的思路是利用隊列來存儲每一個進程的收發指令。一旦找到匹配的指令,則將這一對出隊列。直到某一次找不到匹配的指令了,退出循環。再判斷是不是所有的進程對應的收發指令隊列都爲空。如果全部爲空,則該程序不存在死鎖,否則進程存在死鎖。
因爲每一個進程有的收發指令的個數是不同的,因此需要處理這樣不定數的輸入。這裏用到了stringstream來進行處理。即
getline(cin,line);//輸入一行字符串
stringstream ss(line);
while(ss >> ins){//進行字符串分割。並賦值給ins
cout<<ins<<endl;
}
另外還要值得注意的是,進程n的最多可達10的4次方。因此n可能不止一位數,所有在做題的過程中,不能默認每一個收發指令的長度是2。這樣就大錯特錯了!
#include <bits/stdc++.h>
using namespace std;
struct node{
bool RS;//標記狀態,接還是發
int num;//進程號
node(bool r,int n){
RS = r;
num = n;
}
};
int main(){
int T,n;
cin>>T>>n;
getchar();//喫掉換行符
while(T--){
//依次判斷T個程序是否存在死鎖
vector<queue<node>> v(n); // 用戶存放進程
string line,ins;
//初始化各進程的首發指令
for(int i=0;i<n;i++){
getline(cin,line);//輸入一行字符串
stringstream ss(line);
while(ss >> ins){
// cout<<ins<<endl;
bool RS = ins[0] == 'R' ? 0 : 1;//R爲0
//進程號不一定在0-9,所以進程號可能是多位!!!
int num = stoi(ins.substr(1));//取出進程號
v[i].emplace(RS,num);//c++11新特性。相當於v.push(node{RS,num}),比起push內存消耗更少
// v[i].push(node{RS,num});//實測這兩個好像都可以
}
}
bool flag = true;//表示是否有匹配的
while(flag){
bool isfind = false;
//一直去找匹配的收發指令
for(int i=0;i<n;++i){
if(v[i].empty()) continue;
node tmp = v[i].front();//取出第
int target = tmp.num;//取出收發指令對應的進程號
if(!v[target].empty()){//收發指令匹配
if(v[target].front().RS != tmp.RS && v[target].front().num == i ){
v[target].pop();
v[i].pop();//出隊列
isfind = true;
}
}
}
//找不到匹配的元素了
if(isfind == false){
break;
}
}
flag = true;
//判斷指令全部匹配完。即判斷隊列是否爲空即可
for (int i=0;i<n;++i){
if(!v[i].empty()){
flag = false;
break;
}
}
if(flag){
cout<<0<<endl;
}else{
cout<<1<<endl;
}
}
}