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的感觉很不错哦。
最后,自律才能更强。
欢迎大家批评改正!!!

发布了39 篇原创文章 · 获赞 2 · 访问量 3410

猜你喜欢

转载自blog.csdn.net/weixin_43581819/article/details/104095427