迷宫问题

介绍

迷宫问题一般深度优先遍历或者广度优先遍历解决,辅助数据结构使用栈或者队列。使用栈解决该问题时,将栈顶能达到的一个位置入栈,若发现该路不通,则退栈,通过栈顶元素继续访问其他可达到的位置,直到走完整个迷宫。若使用非循环队列,将队头能到达的所有位置入队,并记录该位置的前驱为队头元素,最后通过队列的元素的前驱记录可得到整个迷宫的路线。

问题描述

迷宫问题
有一个迷宫地图,有一些可达的位置,也有一些不可达的位置(障碍、墙壁、边界)。从一个位置到下一个位置只能通过向上(或者向右、或者向下、或者向左)走一步来实现,从起点出发,如何找到一条到达终点的通路。本文将用两种不同的解决思路,四种具体实现来求解迷宫问题。

用二维矩阵来模拟迷宫地图,1代表该位置不可达,0代表该位置可达。每走过一个位置就将地图的对应位置标记,以免重复。找到通路后打印每一步的坐标,最终到达终点位置。

使用不循环队列

原理描述
先第一个位置入队,将队头能到达的所有位置入队,并记录该位置的前驱为队头元素,最后通过队列的元素的前驱记录可得到整个迷宫的路线。
根结点入队

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

算法描述

#include <stdio.h>
#define Maxsize 100
#define N 4
int M[N + 2][N + 2] =
{
{ 1,1,1,1,1,1},
{ 1,0,1,1,1,1},
{ 1,0,1,0,1,1},
{ 1,0,0,0,1,1},
{ 1,1,0,0,0,1},
{ 1,1,1,1,1,1},
};
struct path
{
	int i, j, p;
}Q[Maxsize];
int front = -1;
int rear = -1;
void print(int front)
{
	int k = front, i = 0, j;
	while (k != 0)
	{
		j = k;
		k = Q[k].p;
		Q[j].p = -1;
	}
	printf("迷宫最快捷路径如下:\n");
	k = 0;
	while (k<Maxsize)
	{
		if (Q[k].p == -1)
		{
			i++;
			printf("(%d,%d)\t", Q[k].i, Q[k].j);
			M[Q[k].i][Q[k].j] = 0;
			printf("\n");
		}
		k++;
	}
	printf("\n迷宫最快捷路径如图所示:\n");
	for (i = 0; i<N + 2; i++)
	{
		for (j = 0; j<N + 2; j++)
		{
			printf("%3d", M[i][j]);
		}
		printf("\n");
	}
}
int labyrinth(int x1, int y1, int x2, int y2)
{
	int i, j, find = 0, di;
	rear++;
	Q[rear].i = x1; Q[rear].j = y1; Q[rear].p = -1;
	M[1][1] = -1;
	while (front <= rear && find == 0)
	{
		front++;
		i = Q[front].i; j = Q[front].j;
		if (i == x2 && j == y2)
		{
			find = 1;
			print(front);
			return 1;
		}
		for (di = 0; di<4; di++)
		{
			switch (di)
			{
			case 0:
				i = Q[front].i - 1; j = Q[front].j; break;
			case 1:
				i = Q[front].i; j = Q[front].j + 1; break;
			case 2:
				i = Q[front].i + 1; j = Q[front].j; break;
			case 3:
				i = Q[front].i; j = Q[front].j - 1; break;
			}
			if (M[i][j] == 0)
			{
				rear++;
				Q[rear].i = i; Q[rear].j = j; Q[rear].p = front;
				M[i][j] = -1;
			}
		}
	}
	return 0;
}
void main()
{
	labyrinth(1, 1, N, N);
	getchar();
}

运行结果
在这里插入图片描述

使用栈

使用栈的思路较为简单,将栈顶能达到的一个位置入栈,若发现该路不通,则退栈,通过栈顶元素继续访问其他可达到的位置,直到走完整个迷宫。

迷宫数据
本文算法将迷宫数据存放于一个文件中,从文件中读取迷宫矩阵,最后使用栈解决迷宫问题。
{ 1,1,1,1,1,1},
{ 1,0,1,1,1,1},
{ 1,0,1,0,1,1},
{ 1,0,0,0,1,1},
{ 1,1,0,0,0,1},
{ 1,1,1,1,1,1},

算法描述

#include <stdio.h>
#include <stdlib.h>

#define maxsize 20

typedef struct Matrix{
	int data[maxsize][maxsize];
	int rowNum;
	int colNum;
}Matrix;

typedef struct Elem{
	int i;	//横坐标 
	int j;	//纵坐标 
}Elem; 
//从文本中读入数据 
int readMatrix(Matrix * matrix,const char * path){
	FILE * fp;
	int i,j;
	char c;
	if((fp = fopen(path,"r")) == NULL){
		printf("文件打开失败\n");
		return 0;
	}
	i = 0;
	j = 0;
	while((c = fgetc(fp)) != EOF){		//读取一个字符 
		if(c == '\n'){					//若读取到换行符则从矩阵的下一行开始赋值 
			j = 0;
			i++;
			continue;
		}
		if(c == ' '){					//不读取空格 
			continue;
		}
		matrix->data[i][j] = c - 48;	//将字符转换为数字 
		j++;
	}
	matrix->rowNum = i + 1;				 
	matrix->colNum = j;
	if(fp != NULL){
		fclose(fp);
		fp = NULL;
	}
	return 1;
}
//显示迷宫 
void showMatrix(Matrix * matrix){
	int i,j;
	for(i = 0; i<matrix->rowNum; i++){
		for(j = 0; j < matrix->colNum; j++){
			printf("%3d",matrix->data[i][j]);
		}
		printf("\n");
	}
}

//寻找迷宫路劲 
int computePath(Matrix * matrix,int x1,int y1,int x2,int y2){		
	Elem stack[maxsize * maxsize];
	int top;
	int i,j,k,find,dir,_i,_j;
	top = -1;
	
	//先将迷宫中的入口加入到栈中 
	top ++;
	stack[top].i = x1;
	stack[top].j = y1;
	matrix->data[x1][y1]=-1;
	while(top > -1){
		i=stack[top].i;//取栈顶元素
		j=stack[top].j;	
		matrix->data[i][j] = -1;
		if(i==x2&&j==y2) {
			printf("找到迷宫路劲:\n");
			for(k=0; k<=top; k++) {
				printf("(%d,%d)\n",stack[k].i,stack[k].j);
				_i = stack[k].i;
				_j = stack[k].j;
				matrix->data[_i][_j] = 2;
			}
			printf("\n");
			return 1; 
		}	
		find = 0;
		dir = 0;
		while(dir<4&&find==0) {		//遍历当前位置的4个方向 
			switch(dir) {

				case 0:
					i=stack[top].i-1;//向上 
					j=stack[top].j;
					break;
				case 1:
					i=stack[top].i; //向右 
					j=stack[top].j+1;
					break;
				case 2:
					i=stack[top].i+1;//向下 
					j=stack[top].j;
					break;
				case 3:
					i=stack[top].i;
					j=stack[top].j-1;//向左 
					break;
			}
			if(matrix->data[i][j]==0) {
				find=1; 
				break;
			}
			dir ++;
		}
		if(find==1) {	//如果发现有路劲,则讲路劲坐标入栈 
			top++;
			stack[top].i=i;
			stack[top].j=j;
			matrix->data[i][j]=-1;
		} else {		//否则将走不通,往回走,退栈 
			matrix->data[stack[top].i][stack[top].j]=-1;
			top--;
			if(top < 0){
				showMatrix(matrix);
				return 0;
			}
		}
	}
}

int main(){
	int flag;
	Matrix matrix;
	readMatrix(&matrix,"d:/1.txt");
	printf("读取到迷宫数据:\n");
	showMatrix(&matrix);
	printf("\n");
	flag = computePath(&matrix,1,1,matrix.rowNum-2,matrix.colNum-2);
	printf("\n");
	if(!flag){
	 	printf("未找到迷宫路劲:\n");
	 	return 0;
	}
	printf("打印路线图迷宫数据(2为所走路线):\n");
	showMatrix(&matrix);
	return 0;
} 

总结

本文提供了两种解决迷宫问题的思路,其一为使用广度优先遍历(使用队列)解决,其二为使用深度优先遍历(使用栈)来解决,本文主要描述了广度优先遍历迷宫的思路,提供了算法描述和实验结果,另外也提供了栈的算法描述和实验数据。

  • 15
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值