PTA:7-117 地下迷宮探索 (30分)(dfs搜索加解析)

7-117 地下迷宮探索 (30分)

地道戰是在抗日戰爭時期,在華北平原上抗日軍民利用地道打擊日本侵略者的作戰方式。地道網是房連房、街連街、村連村的地下工事,如下圖所示。
在這裏插入圖片描述
我們在回顧前輩們艱苦卓絕的戰爭生活的同時,真心欽佩他們的聰明才智。在現在和平發展的年代,對多數人來說,探索地下通道或許只是一種娛樂或者益智的遊戲。本實驗案例以探索地下通道迷宮作爲內容。
在這裏插入圖片描述
假設有一個地下通道迷宮,它的通道都是直的,而通道所有交叉點(包括通道的端點)上都有一盞燈和一個開關。請問你如何從某個起點開始在迷宮中點亮所有的燈並回到起點?
輸入格式:
輸入第一行給出三個正整數,分別表示地下迷宮的節點數N(1<N≤1000,表示通道所有交叉點和端點)、邊數M(≤3000,表示通道數)和探索起始節點編號S(節點從1到N編號)。隨後的M行對應M條邊(通道),每行給出一對正整數,分別是該條邊直接連通的兩個節點的編號。

輸出格式:
若可以點亮所有節點的燈,則輸出從S開始並以S結束的包含所有節點的序列,序列中相鄰的節點一定有邊(通道);否則雖然不能點亮所有節點的燈,但還是輸出點亮部分燈的節點序列,最後輸出0,此時表示迷宮不是連通圖。

由於深度優先遍歷的節點序列是不唯一的,爲了使得輸出具有唯一的結果,我們約定以節點小編號優先的次序訪問(點燈)。在點亮所有可以點亮的燈後,以原路返回的方式回到起點。

輸入樣例1:
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

輸出樣例1:
1 2 3 4 5 6 5 4 3 2 1

輸入樣例2:
6 6 6
1 2
1 3
2 3
5 4
6 5
6 4

輸出樣例2:
6 4 5 4 6 0

思路:
該題困擾我的問題是,如何保存回溯的路徑?
比如樣例:
輸入:

6 5 1
1 2
1 3
3 4
3 5
5 6

輸出:

1 2 1 3 4 3 5 6 5 3 1

該樣例畫圖如下:
在這裏插入圖片描述
從該樣例可以看出,題目要求的是輸出完整的路徑,也就是整個開燈的過程。
從1出發,按照小號優先,到達2,走不通了,又回到了1,再從1出發到達3,,,依次類推,完成。
具體過程見AC代碼:

#include<bits/stdc++.h>
using namespace std;
int vis[1010],r[1010][1010],path[1010];
int n,m,s,j=0,cnt=1;  //cnt統計可以點亮的燈個數 

void dsf(int x){
	for(int i=1; i<=n; i++){
		if(r[x][i]&&!vis[i]){
			cnt++;
			vis[i]=1;
			
			//核心************* 
			path[j++]=i;//保存去的結點 
			dsf(i);
			path[j++]=x; //保存回去的路 
			//************* 
		} 
	}
} 
 
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m>>s;
	while(m--){
		int a,b;
		cin>>a>>b;
		r[a][b]=1;
		r[b][a]=1;
	}
	path[j++]=s; 
	vis[s]=1;
	dsf(s);
	for(int i=0; i<j; i++){
		if(i!=0) cout<<" "; 
		cout<<path[i];
	}
	if(cnt<n) cout<<" 0"<<endl;
	return 0;
}

參考博客:https://blog.csdn.net/lyw_321/article/details/78105328
總結
通過該題,知道了做題時不用想的太麻煩(如果太麻煩的話,很有可能就是你的思路不是很好),發散一下思維,很難的問題可能也就兩行代碼。
另外就是,之前一直dfs都在return,這次使用了一次不帶return的感覺很不錯哦。
最後,自律才能更強。
歡迎大家批評改正!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章