蛮力法 —— 求解迷宫问题 —— DFS和BFS

10 篇文章 0 订阅
3 篇文章 0 订阅

求解迷宫问题

问题描述:
有如图8×8的迷宫
OXXXXXXX
OOOOOXXX
XOXXOOOX
XOXXOXXO
XOXXXXXX
XOOOOXOO
XXXXXXXO
其中,O表示通路方块,X表示障碍方块。
假设入口位置为(0,0)出口为右下角方块位置(7,7)设计一个程序求指定入口到出口的一条迷宫路径。

分析

用n表示迷宫大小,用二维数组Maze存放迷宫,从(x,y)方块可以试探上、下、左、右4个方位。假设总是按从方位0到方位3的顺序试探,各方位对应的水平方向偏移量H[4]={0,1,0,-1}、垂直偏移量V[4]={-1,0,1,0}
在这里插入图片描述

  • 思路一:深度优先遍历DFS

从(x,y)出发(初始为入口)搜索目标(出口)。对于当前方块(x,y),需要试探4个相邻的方块将对应的迷宫值由‘O’改为‘ ’(空格字符),当回过来时将其迷宫值恢复为‘O’。

代码1:

#include<stdio.h>
#define MAxN 10

int n=8;
char Maze[MAxN][MAxN]=
{
	{'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','X','X','X','X'},
	{'X','O','X','X','O','O','O','X'},
	{'X','O','O','O','O','X','O','X'},
	{'X','O','O','O','O','X','O','O'},
	{'X','X','X','X','X','X','X','O'}
 };
 int H[4]={0,1,0,-1};   //水平偏移量,下标对应方位号1~3 
 int V[4]={-1,0,1,0};    //垂直偏移量 
 void disp(){             //输出一条迷宫路径 
 	for(int i=0;i<n;i++){
 		printf(" ");
 		for(int j=0;j<n;j++)
 		printf("%c",Maze[i][j]);
 		printf("\n");
	 }
 } 
 void DFS(int x,int y){   //求从(x,y)出发的一条迷宫路径 
 	if(x==n-1&&y==n-1)   //找到一条路径输出 
 	{                
 		Maze[n-1][n-1]=' ';
 		disp();
		 return; 
	 }
	 else
	 {
	 	for(int k=0;k<4;k++)   //试探每一个方位 
	 	if(x>=0&&y>=0&&x<n&&y<n&&Maze[x][y]=='O')
	 	{     //若(x,y)方块是可以走的 
	 		Maze[x][y]=' ';  //将该方块迷宫值设置为空格字符 
	 		DFS(x+V[k],y+H[k]);   //查找(x,y)周围的每一个相邻方块 
	 		Maze[x][y]='O';    //若从该相邻方块出发没有找到路径,恢复(x,y)迷宫值 
	}
   }
 }
 int main(){
 	int x=0,y=0;    //指定入口,出口默认(n-1,n-1) 
 	printf("一条迷宫路径: \n");
 	DFS(x,y);   //求(0,0)->(7,7) 
 }

在这里插入图片描述


  • 思路二:广度优先遍历BFS

一定是最短路径

从(x,y)出发(初始为入口)搜索目标(出口)。由于在STL中queue不能顺序遍历,这里用一个数组作为非循环队列,front和rear分别为对头和队尾(初始值均设置为-1),每个进队元素有唯一下标

struct Position
{
	int x,y;  //当前方块位置 
	int pre;  //前驱方块下标 
};

定义队列:

Position qu[MAXQ];
int front=-1,rear=-1;

首先,将根入口方块(其pre置为-1)进队,队列不空时循环:出队方块p1作为当前方块(在队列数组中的下标为front),若p1为出口,通过队列数组qu反向退出迷宫路径并输出;
否则查找p1的每一个相邻方块p2,若p2位置有效(即p2.x>=0&&p2.y>=0&&p2.x<n&&p2.y<n)并且可走(Maze[p2.x][p2.y]=‘O’),置p2.pre=front(表示p2的前驱方块是p1)并将p2方块进队。

代码2:

#include<stdio.h>
#define MAXQ 100
#define MAxN 10

int n=8;
char Maze[MAxN][MAxN]=
{
	{'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','X','X','X','X'},
	{'X','O','X','X','O','O','O','X'},
	{'X','O','O','O','O','X','O','X'},
	{'X','O','O','O','O','X','O','O'},
	{'X','X','X','X','X','X','X','O'}
 };
 int H[4]={0,1,0,-1};   //水平偏移量,下标对应方位号1~3 
 int V[4]={-1,0,1,0};    //垂直偏移量 
 struct Position  //队列元素类型 
{
	int x,y;  //当前方块位置 
	int pre;  //前驱方块下标 
};
Position qu[MAXQ];   //定义队列qu 
int front=-1,rear=-1;  //对头和队尾 
void disp(int front){   //输出迷宫路径 
	int i,j;
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)   //将所有*改为O 
	if(Maze[i][j]=='*')  
	Maze[i][j]='O';
	int k=front;
	while(k!=-1)
	{
		Maze[qu[k].x][qu[k].y]=' ';   //路径上的方块改为‘’ 
		k=qu[k].pre;
	}
	for(i=0;i<n;i+=)    //输出迷宫路径 
	{
		printf(" ");
		for(int j=0;j<n;j++)
		printf("%c",Maze[i][j]);
		printf("\n");
	}
}
void BFS(int x,int y){   //求从(x,y)出发的一条迷宫路径
	Position p,p1,p2;
	p.x=x;    //建立入口节点 
	p.y=y;
	p.pre=-1;
	Maze[p.x][p.y]='*';   //改为'*'避免重复查找 
	rear++;      //入口方块入队 
	qu[rear]=p;
	while(front!=rear){  //队不空时循环 
		front++;
		p1=qu[front];    //出队方块p1 
		if(p1.x==n-1&&pi.y==n-1)  //找到出口 
		{
			disp(front);  //输出路径 
			return;
		}
		for(int k=0;k<4;k++){
			p2.x=p1.x+V[k];  //试探p1的每个相邻方位 
			p2.y=p1.y+H[k];   //找到p1的相邻方位p2 
			if(p2.x>=0&&p2.x<n&&p2.y>=0&&p2.y<n&&Maze[p2.x][p2.y]=='O')
			{   //方块p2有效并且可走 
				Maze[p2.x][p2.y='*'];   //改为'*'避免重复查找 
				p2.pre=front;
				rear++;
				qu[rear]=p2;		//方块p2进队 
				}
		}
	}
}
int main(){
 	int x=0,y=0;    //指定入口,出口默认(n-1,n-1) 
 	printf("一条迷宫路径: \n");
 	DFS(x,y);   //求(0,0)->(7,7) 
 }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值