c++使用深度优先算法和广度优先算法解决迷宫问题

求从迷宫左上角(0,0)到右下角(M-1,N-1)的路径。
M x N的迷宫如下:O代表可通行,X代表不可通行。每次只能往上下左右四个方向走一步。
{'O','X','X','X','X','X','X','X'
'O','O','O','O','O','X','X','X'
'X','O','X','X','O','O','O','X'
'X','O','X','X','O','X','X','O'
'X','O','X','X','O','X','X','X'
'X','O','X','X','O','O','O','X'
'X','O','O','O','O','X','O','O'
'X','X','X','X','X','X','X','O'}
 

一、深度优先算法求出所有到达出口的路径:

#include <iostream>
#include<vector>
using namespace std;

#define m 8//迷宫的长度
#define n 8//迷宫的宽度

int s=1;//答案个数记录

typedef struct location{
	int xx,yy;
}location;//位置

void findpath(location L, int **map, vector<string>& path) {
	// 越界检查
	if (L.xx < 0 || L.yy < 0 || L.xx >= m || L.yy >= n || map[L.xx][L.yy] == 0) {
		return;
	}
	
	// 到达终点
	if (L.xx == m - 1 && L.yy == n - 1) {
		s++;
		string lo = "(" + to_string(L.xx) + "," + to_string(L.yy) + ")";
		path.push_back(lo);
		cout << "第" << s << "种路径为:";
		for (const string& p : path) {
			cout << p << " ";
		}
		cout << endl;
		path.pop_back();
		return;
	}
	
	// 标记为已访问
	map[L.xx][L.yy] = 0;
	
	// 四个方向进行搜索
	vector<location> directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
	for (const auto& dir : directions) {
		location next = {L.xx + dir.xx, L.yy + dir.yy};
		string lo = "(" + to_string(L.xx) + "," + to_string(L.yy) + ")";
		path.push_back(lo);
		findpath(next, map, path);
		path.pop_back();
	}
	
	// 回溯,恢复状态
	map[L.xx][L.yy] = 1;
}
int main(){
	location L;
	L.xx=0;
	L.yy=0;
	
	int **map=new int*[m];
	for(int i=0;i<m;i++){
		map[i]=new int[n];
	}
	int Map[m][n]={
		{1,0,0,0,0,0,0,0},
		{1,1,1,1,1,0,0,0},
		{0,1,0,0,1,1,1,0},
		{0,1,0,0,1,0,0,1},
		{0,1,0,0,1,0,0,0},
		{0,1,0,0,1,1,1,0},
		{0,1,1,1,1,0,1,1},
		{0,0,0,0,0,0,0,1}
	};//迷宫地图使用二维数组存储
	
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			map[i][j]=Map[i][j];
		}
	}
	
	if(map[0][0]==0){
		cout<<"这个迷宫没有出路!";
		return 0;
	}	
	
	vector<string> path;
	findpath(L,map,path);
	if(s==0){
		cout<<"没有找到这个迷宫的出路!";
	}
	return 0;
}

深度优先搜索运用递归遍历通路,并用栈存储正确的迷宫路径。

输出结果:

二、广度优先搜索找出最短路径:

#include <iostream>
#include <vector>
#include<queue>
#include <string>
#include<bits/stdc++.h>


using namespace std;


#define m 8 // 迷宫的长度
#define n 8 // 迷宫的宽度

int s = 0; // 答案个数记录

using namespace std;
struct location{	
	int xx;//记录坐标(x,y)	
	int yy;	
	int f;//记录是由谁扩展而来,即父亲节点是谁
	int h;//这个点在que里的位置
	
};
struct location que[2501];

const 	vector<location> directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

void output(int x){
	if(x==0){
		cout<<"最短路径为:(0,0) ";
		return;
	}
	output(que[x].f);
	cout<<"("<<que[x].xx<<","<<que[x].yy<<") ";
}

	
	
void findpath(location L, int map[][n],  queue<location>& path) {
	int i=0;
	if(L.xx>=m||L.yy>=n){
		return;
	}
	path.push(L);
	que[i]=L;
	while(!path.empty()){
		L=path.front();
		map[L.xx][L.yy]=0;
		if(L.xx==m-1&L.yy==n-1){
			output(i);
			break;
		}
		// 四个方向进行搜索
		for (const auto& dir : directions) {
			location next = {L.xx + dir.xx, L.yy + dir.yy};
			if (map[next.xx][next.yy]==1){
				next.f=L.h;
				que[++i]=next;
				next.h=i;
				path.push(next);
				
			}
		}
		path.pop();
		
	}
}

int main() {
	location L;
	L.xx = 0;
	L.yy = 0;
	L.f=0;
	L.h=0;
	
	int Map[m][n] = {
		{1, 0, 0, 0, 0, 0, 0, 0},
		{1, 1, 1, 1, 1, 0, 0, 0},
		{0, 1, 0, 0, 1, 1, 1, 0},
		{0, 1, 0, 0, 1, 0, 0, 1},
		{0, 1, 0, 0, 1, 0, 0, 0},
		{0, 1, 0, 0, 1, 1, 1, 0},
		{0, 1, 1, 1, 1, 0, 1, 1},
		{0, 0, 0, 0, 0, 0, 0, 1}
	}; // 迷宫地图使用二维数组存储
	
	queue<location> path;
	
	findpath(L, Map, path);
	
	return 0;
}

广度优先搜索可以理解为许多人同时开始走迷宫,每个人都在同一时间内向上、下、左、右走一步,最先走到终点的路径就是最短路径。

从根节点开始找到所有能走的点进行入队,根节点出队。以此类推,最先到达终点的为最短路径。此时从终点使用递归寻找该节点的父节点进行逆向输出。

que中保存了所有可以走的路径节点。每个节点有坐标、自己的索引值以及父节点的索引值用来从结果逆向输出路径。

输出结果:

三、从文件中打开地图: 

#include <iostream>
#include<vector>
#include<fstream>
using namespace std;

int s=0;//答案个数记录


typedef struct location{
	int xx,yy;
}location;//位置

int M,N;

int** readfile(){
	fstream file;//创建fstream对象
	file.open("map.txt",std::ios::in);
	if (!file) {
		std::cerr << "文件打开失败!" << std::endl;
		return NULL;//文件打开失败
	}
	string line;
	
	int i=0;
	int j=0;
	int **map=new int*[M];
	while(getline(file,line)){
		map[i]=new int[N]; 
		for(char c:line){
			if(c=='1'||c=='O'){
				map[i][j++]=1;
			}else if(c=='0'||c=='X'){
				map[i][j++]=0;
			}
		}
		i++;
		j=0;
	}
	return map;
}

void findpath(location L,int **map,vector<string> path){
	if (L.xx < 0 || L.yy < 0 || L.xx >= M || L.yy >= N || map[L.xx][L.yy] == 0) {
		return;
	}
	string lo = "(" + to_string(L.xx) + "," + to_string(L.yy) + ")";
	path.push_back(lo);
	map[L.xx][L.yy]=0;
	if(L.xx==M-1&&L.yy==N-1){
		
		cout<<"第"<<++s<<"种路径为:";
		for(string p:path){
			cout<<p<<" ";
		}
		cout<<endl;
		path.pop_back();
	}//如果到达终点,输出路径
	location tmp=L;
	L.xx += 1;
	findpath(L, map, path);
	L=tmp; 
	
	L.yy += 1;
	findpath(L, map, path);
	L=tmp; 
	
	L.xx -= 1;
	findpath(L, map, path);
	L=tmp;
	
	L.yy -= 1;
	findpath(L, map, path);
	L=tmp; 	
	
	path.pop_back();
	map[L.xx][L.yy]=1;
	
}
int main(){
	location L;
	L.xx=0;
	L.yy=0;
	
	cout<<"请输入地图长宽:";
	cin>>M>>N;
	int **Map=readfile();
	if(Map[0][0]==0){
		cout<<"这个迷宫没有出路!";
		return 0;
	}
	vector<string> path;
	findpath(L,Map,path);
	if(s==0){
		cout<<"没有找到这个迷宫的出路!";
	}
	return 0;
}

这一问中添加了readfile()函数用来从文件中解析地图数据,并使用动态数组存储地图。

输出结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值