ccf csp-201903034-消息傳遞接口(隊列)

背景

消息傳遞接口(MPI)是一個並行計算的應用程序接口,常用於超級計算機、計算機集羣等環境下的程序設計。

題目

老師給了 T 份 MPI 的樣例代碼,每份代碼都實現了 n 個進程通信。這些進程標號從 0 到 n − 1,每個進程會順序執行自己的收發指令,如:“S x”,“R x”。“S x”表示向x 號進程發送數據,“R x”表示從 x 號進程接收數據。每一對收發命令必須匹配執行才能生效,否則會“死鎖”。
舉個例子,x 號進程先執行發送命令“S y”,y 號進程必. 須. 執行接送命令“R x”,這一對命令才執行成功。否則 x 號進程會一直等待 y 號進程執行對應的接收命令。反之,若 y 號進程先執行接收命令“R x”,則會一直等待 x 號進程執行發送命令“S y”,若 x號進程一直未執行發送命令“S y”,則 y 號進程會一直等待 x 號進程執行對應的發送命令。上述這樣發送接收命令不匹配的情況都會造成整個程序出現“死鎖”。另外,x
號進程不會執行“S x”或“R x”,即不會從自己的進程收發消息。.現在老師請你判斷每份樣例代碼是否會出現“死鎖”的情況。每個進程的指令最少有 1 條,最多有 8 條,這些指令按順序執行,即第一條執行完畢,才能執行第二條,依次到最後一條。

輸入

從標準輸入讀入數據。
輸入第一行兩個正整數 T, n,表示有 T 份樣例代碼,實現了 n 個進程通信。
接下來有 T × n 行,每行有若干個(1 − 8 個)字符串,相鄰之間有一個空格隔開,表示相應進程的收發指令。不存在非法指令。對於第 2 + i, 0 ≤ i ≤ (T × n − 1) 行,表示第 i ÷ n(商)份代碼的 i KQ/ n(餘數)號進程的收發指令。
(比如,“S1”表示向 1 號進程發送消息,“R1”表示從 1 號進程接收消息。細節請參考樣例。)

輸出

輸出到標準輸出。
輸出共 T 行,每行一個數字,表示對應樣例代碼是否出現“死鎖”的情況。1 表示死鎖,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
輸出樣例1
0
1
0
樣例解釋1

第 1 份代碼中,(1)0 號進程執行的“R1”和 1 號進程執行的“S0”成功執行;(2)0 號進程執行的“S1”和 1 號進程執行的“R0”成功執行,所以未發生“死鎖”,程序順利運行。
第 2 份代碼中,(1)0 號進程執行的“R1”和 1 號進程執行的“R0”一直在等待發送命令,進入“死鎖”狀態。

輸入樣例2
2 3
R1 S1
R2 S0 R0 S2
S1 R1
R1
R2 S0 R0
S1 R1
輸出樣例2
0
1
樣例解釋2

第 1 份代碼中,(1)2 號進程執行的“S1”和 1 號進程執行的“R2”成功執行;(2)0 號進程執行的“R1”和 1 號進程執行的“S0”成功執行;(3)0 號進程執行的“S1”和 1 號進程執行的“R0”成功執行;(4)1 號進程執行的“S2”和 2 號進程執行的“R1”成功執行;所以未發生“死鎖”,程序順利運行。
第 2 份代碼中,(1)2 號進程執行的“S1”和 1 號進程執行的“R2”成功執行;(2)
0 號進程執行的“R1”和 1 號進程執行的“S0”成功執行;(3)1 號進程執行的“R0”
和 2 號進程執行的“R1”一直在等待發送命令;進入“死鎖”狀態。

思路:

用隊列存儲進程的指令集合,每一個隊列對應一個進程的指令集合。
1、入口:從第一個非空隊列開始
2、迭代體:消第一列/消隊首元素(消的含義是兩兩進程的收發指令能匹配)消完一次即出隊一次。

  • 其中,消第一列又是 迭代 地消:匹配方i和被匹配方other消完後,被匹配方other變成了下一次迭代的匹配方i,以此迭代下去,類似於斐波那契數列

3、出口:不能再消/只剩最後一個隊列非空

超時問題解決:

1、能用memset儘量不用fill !
2、能用if-else結構儘量不用if-if結構 !

代碼如下

#include<iostream>
#include<cstring>
#include<queue>
const int N = 10005;
using namespace std;
int t,n,tmp;
struct node{
	int no;
	int op;
};
queue<node> q[N];
void fun()
{
	int visit[N]={0},i = 0,flag = 1,other;
	while(flag){
		//易忘
		i = 0;
		flag = 0;
		//fill(visit,visit+N,0); 
		memset(visit, 0, sizeof(visit));
		while(i < n && q[i].empty()) i++;
		if(i == n) break;
		other = q[i].front().no;
		while(!flag&&!visit[other]&&!q[other].empty()){
			if(q[other].front().op!=q[i].front().op&&q[other].front().no==i){
				flag = 1;
				q[other].pop();
				q[i].pop();
			}
			visit[i] = 1;
			visit[other] = 1;
			i = other;
			other = q[i].front().no;
		}
	}
	int ans = 0;
	for(int i = 0; i < n; i++){
		if(!q[i].empty()){
			ans = 1;
			queue<node> empty;
			swap(empty, q[i]);
		}
	}
	cout<<ans<<endl;
}
int main()
{
	string s;int op,no;
	scanf("%d%d\n", &t, &n);
	while(t--){
		for(int i = 0; i < n; i++){
			getline(cin, s);
			for(int j = 0; j < s.length(); j++){
				if(s[j] == ' ')continue; 
				else if(s[j]=='R'||s[j]=='S'){
					op=(s[j++]=='R')?0:1;
					no = 0;
					while(j<s.length()&&s[j]!=' '){
						no = no*10+(s[j++]-'0');
					}
					//no=stoi(tmp);
					q[i].push({no,op});
				}
			}
		}
		fun();
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章