題目解讀:
老師給了T份樣例,有n個進程,這n個進程之間可以receive接收和send發送消息(如R1,S2....)。R,S即接收和發送的進程號要對應起來,例如R1必須與S0配對。
當開始時,初始所有的進程為准備就緒的狀態,然后開始從第一個進程的第一個消息A開始,如果A消息要和第x號進程進行R 或 S,就看X號進程隊列的頭部B是否能和A配對,如果能配對,就繼續第一個進程的下一個消息;如果不能,就先處理X號進程,看B要和哪一個進程配對,配對好了就繼續X號里的下一個消息,直到能找到和A配對的消息,這是一個遞歸的過程。當然,在這過程中,如果發現有進程處於一直等待狀態,或配對過程中發現某一方進程已經為空,這份樣例的代碼就處於“鎖死”了。
知識點:
queue
#include<queue> //頭文件 queue<int> test; //初始化一個int型的隊列名為test test.empty() ; //查看隊列是否為空 test.size(); //返回隊列大小 test.front(); //返回隊列下一個元素 test.back(); // 返回隊列最后一個元素 test.push(); //添加一個元素 test.pop(); //刪除隊列下一個元素 test.emplace(); //構造和插入元素 test.swap(); //交換內容
istringstream:
istringstream類用於執行C++風格的串流的輸入操作、
這里用於將字符串從空格處分開
atoi():
C庫函數,將數值型字符轉化為數值
c_str()
通過string類對象的成員函數c_str()把string 對象轉換成c中的字符串樣式,這樣就可以在C庫函數里使用了
代碼:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<sstream> #include<queue> using namespace std; const int MAXN=10005; //每個消息的結構 struct Mes{ char flag;//接收消息 int target;//目標進程 }; //進程 struct Pro{ queue<Mes> task; }; Pro pro[MAXN];//進程數組 int wait[MAXN];//進程狀態 int receiveM(int from,int to); int sendM(int from,int to); int exe(int now) { if(wait[now]==1) return -1;//判斷當前進程是否處於等待 if(pro[now].task.empty()) return 0;//隊列為空,則表示該進程消息已經處理完畢 Mes cur=pro[now].task.front(); if(cur.flag=='R') { wait[now]=1;//現在該進程在進行任務,其他消息只能等待 if(receiveM(now,cur.target)==-1) return -1; //消息接收成功 pro[now].task.pop();//消息處理成功,從消息隊列里移除 wait[now]=0;//消息處理完畢,進程繼續准備 if(exe(now)==-1) return -1;//處理下一個消息 return 0; } else if(cur.flag=='S') { wait[now]=1; if(sendM(now,cur.target)==-1) return -1; //成功配對 wait[now]=0; pro[now].task.pop(); if(exe(now)==-1) return -1; return 0; } } int receiveM(int from,int to) { if(wait[to]==1) return -1; if(pro[to].task.empty()) return -1;//如果該進程已經沒有消息了,接不會執行 Mes cur=pro[to].task.front(); if(cur.flag=='R') { wait[to]=1; if(receiveM(to,cur.target)==-1) return -1;//遞歸處理下一個消息 wait[to]=0; pro[to].task.pop(); if(receiveM(from,to)==0) return 0;//遞歸判斷之前的消息是否可以處理 return -1; } else if(cur.flag=='S') { if(from==cur.target){ pro[to].task.pop(); return 0; } //不能配對成功 wait[to] =1; if(sendM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(receiveM(from,to)==0) return 0; return -1; } } int sendM(int from,int to) { if(wait[to]==1) return -1; if(pro[to].task.empty()) return -1; Mes cur=pro[to].task.front(); if(cur.flag=='R') { if(from==cur.target) { pro[to].task.pop(); return 0; } wait[to]=1; if(receiveM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(sendM(from,to)==0) return 0; return -1; } else if(cur.flag=='S') { wait[to]=1; if(sendM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(sendM(from,to)==0) return 0; return -1; } } int T,n; int main() { scanf("%d %d",&T,&n); getchar();//回車 for(int i=0;i<T;i++) { memset(wait,0,sizeof(wait));//初始化進程狀態 for(int j=0;j<n;j++) { //初始化每個進程的消息隊列 while(!pro[j].task.empty()) pro[j].task.pop(); } for(int j=0;j<n;j++) { //處理輸入 string line; getline(cin,line); istringstream ss(line); string tmp; while(ss>>tmp){ Mes mes; mes.flag=tmp[0];//獲取R,S mes.target=atoi(tmp.c_str()+1);//獲取目標進程 pro[j].task.push(mes); //加入消息隊列 } } int flag=0; for(int j=0;j<n;j++) { if(!pro[j].task.empty()) { if(exe(j)==-1){ //鎖死 flag=1; break; } } } printf("%d\n",flag); } }