首页 > 代码库 > 数据结构与算法学习之路:迷宫问题——回溯思想找出所有路径

数据结构与算法学习之路:迷宫问题——回溯思想找出所有路径

今天小伙伴和我说之前写的那个迷宫问题有些问题,我就改了改,感觉之前写的东西思路也不清晰,也比较乱,就重新写了一篇……别在意哈~


一、迷宫问题描述:

给定一个迷宫,以及起点和终点,通过设计算法,找到一条可以到达终点的路径。解决以后,想办法找到最短路径和所有路径。


二、解决方法:

1、找到一条可达的路径并不难,只要设定方向,然后每个点都去找一个可以走的方向一直向可行方向走就是了。


2、找到最短路径。要找到最短路径,可以尝试广度优先算法——BFS。BFS找图中一点到另一点的最短路径还是很方便的(没有权值),主要思想是,把每一个点可到的状态都算出来,最先到达终点的状态就是最短的路径长度。就这样说可能很抽象,不妨看看下面这张图:


3、找所有路径。找所有路径比较简单的方法是先找出一条路径,然后回溯到上一个点,看看有没有别的地方可以走,再从这个方向往下走。从而不断回溯找到所有路径


三、代码:

找到所有路径的实现方式:


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

#define WALL 1
#define ROAD 0
#define END -1

#define TRUE 1
#define FALSE 0

#define VISITED 1
#define UNVISITED 0
#define BARRIER -1 //四周都是墙的死路

#define MAXSIZE 11 //迷宫每行或每列中点的的最大数量
#define DIR_SIZE 4 //方向
#define STACK_SIZE 128

typedef int Status;

//迷宫中的点
typedef struct Point{
	int x;
	int y;
	Status status;
	Status visited;
}Point;

typedef struct Stack{
	Point point[STACK_SIZE];
	int top;
}Stack, *StackPtr;

void Stack_Init(StackPtr s);
void Stack_Push(StackPtr s, Point point);
void Stack_Pop(StackPtr s);

//搜索所有路径。
//多入口多出口加个起点终点数组,将起点通过循环作为栈底,遍历到达不同终点的路径即可
void Maze_Search(StackPtr s, Point maze[MAXSIZE][MAXSIZE],Point *dir);

int main(){
	StackPtr stack;
	Point dir[DIR_SIZE];
	Point up, down, right, left;
	Point maze[MAXSIZE][MAXSIZE];

	int i, j;

	//初始化迷宫
	for (i = 0; i < MAXSIZE; i++){
		for (j = 0; j < MAXSIZE; j++)
			maze[i][j].status = ROAD;
	}
	for (i = 0; i < MAXSIZE; i++)
		for (j = 0; j < MAXSIZE; j++){
		maze[i][j].x = i;
		maze[i][j].y = j;
		maze[i][j].visited = UNVISITED;
		}

	for (i = 0; i < MAXSIZE; i++){
		maze[0][i].status = WALL;
		maze[10][i].status = WALL;

		maze[0][i].visited = VISITED;
		maze[10][i].visited = VISITED;
	}

	for (i = 0; i < MAXSIZE; i++){
		maze[i][0].status = WALL;
		maze[i][10].status = WALL;

		maze[i][0].visited = VISITED;
		maze[i][10].visited = VISITED;
	}

	maze[1][2].status = WALL;
	maze[1][3].status = WALL;
	maze[1][5].status = WALL;
	maze[1][6].status = WALL;
	maze[1][9].status = WALL;
	maze[2][3].status = WALL;
	maze[2][4].status = WALL;
	maze[2][7].status = WALL;
	maze[2][8].status = WALL;
	maze[2][9].status = WALL;
	maze[3][3].status = WALL;
	maze[3][5].status = WALL;
	maze[3][6].status = WALL;
	maze[3][8].status = WALL;
	maze[4][2].status = WALL;
	maze[4][4].status = WALL;
	maze[4][7].status = WALL;
	maze[4][9].status = WALL;
	maze[5][6].status = WALL;
	maze[5][3].status = WALL;
	maze[5][5].status = WALL;
	maze[5][8].status = WALL;
	maze[6][1].status = WALL;
	maze[6][4].status = WALL;
	maze[6][6].status = WALL;
	maze[6][7].status = WALL;
	maze[6][9].status = WALL;
	maze[7][4].status = WALL;
	maze[7][8].status = WALL;
	maze[7][9].status = WALL;
	maze[8][2].status = WALL;
	maze[8][6].status = WALL;
	maze[9][1].status = WALL;
	maze[9][2].status = WALL;

	maze[1][1].visited = VISITED;
	maze[1][2].visited = VISITED;
	maze[1][3].visited = VISITED;
	maze[1][5].visited = VISITED;
	maze[1][6].visited = VISITED;
	maze[1][9].visited = VISITED;
	maze[2][3].visited = VISITED;
	maze[2][4].visited = VISITED;
	maze[2][7].visited = VISITED;
	maze[2][8].visited = VISITED;
	maze[2][9].visited = VISITED;
	maze[3][3].visited = VISITED;
	maze[3][5].visited = VISITED;
	maze[3][6].visited = VISITED;
	maze[3][8].visited = VISITED;
	maze[4][2].visited = VISITED;
	maze[4][4].visited = VISITED;
	maze[4][7].visited = VISITED;
	maze[4][9].visited = VISITED;
	maze[5][6].visited = VISITED;
	maze[5][3].visited = VISITED;
	maze[5][5].visited = VISITED;
	maze[5][8].visited = VISITED;
	maze[6][1].visited = VISITED;
	maze[6][4].visited = VISITED;
	maze[6][6].visited = VISITED;
	maze[6][7].visited = VISITED;
	maze[6][9].visited = VISITED;
	maze[7][4].visited = VISITED;
	maze[7][8].visited = VISITED;
	maze[7][9].visited = VISITED;
	maze[8][2].visited = VISITED;
	maze[8][6].visited = VISITED;
	maze[9][1].visited = VISITED;
	maze[9][2].visited = VISITED;

	maze[9][9].status = END;

	up.x = -1;
	up.y = 0;
	up.status = ROAD;

	left.x = 0;
	left.y = -1;
	left.status = ROAD;

	right.x = 0;
	right.y = 1;
	right.status = ROAD;

	down.x = 1;
	down.y = 0;
	down.status = ROAD;

	dir[0] = left;
	dir[1] = down;
	dir[2] = right;
	dir[3] = up;

	//输出迷宫
	for (i = 0; i < MAXSIZE; i++){
		for (j = 0; j < MAXSIZE; j++){
			if (maze[i][j].status == WALL)
				printf("▇");
			else
				printf("  ");
		}
		printf("\n");
	}
	printf("\n");

	//初始化保存路径的栈
	stack = (StackPtr)malloc(sizeof(Stack));
	Stack_Init(stack);

	Maze_Search(stack, maze, dir);

	return 0;
}

void Stack_Init(StackPtr s){
	Point temp;

	if (s == NULL)
		return;

	temp.x = 1;
	temp.y = 1;
	temp.status = ROAD;
	temp.visited = VISITED;

	s->top = 0;
	s->point[s->top] = temp;

	return;
}

void Stack_Push(StackPtr s, Point point){
	if (s->top == (STACK_SIZE - 1)){
		printf("栈已满!");
		return;
	}

	s->top += 1;
	s->point[s->top] = point;
}

void Stack_Pop(StackPtr s){
	Point temp;

	if (s->top == -1){
		printf("栈为空!");
		return;
	}

	temp.x = 0;
	temp.y = 0;
	temp.status = ROAD;

	s->point[s->top] = temp;
	s->top -= 1;
}

void Maze_Search(StackPtr s, Point maze[MAXSIZE][MAXSIZE],Point *dir){
	int i,j;

	if (s->point[s->top].status == END){
		for (i = 0; i < MAXSIZE; i++){
			for (j = 0; j < MAXSIZE; j++){
				if (maze[i][j].status == WALL)
					printf("▇");
				else if ((maze[i][j].status == ROAD || maze[i][j].status == END) && maze[i][j].visited == VISITED && maze[i][j].visited != BARRIER)
					printf("※");
				else
					printf("  ");
			}
			printf("\n");
		}
		maze[9][9].visited = UNVISITED;
		Stack_Pop(s);
		printf("\n\n");

		return;
	}

	for (i = 0; i < DIR_SIZE; i++){
		if (maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].status != WALL
				&& maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited != VISITED){
			maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited = VISITED;
			Stack_Push(s, maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y]);

			Maze_Search(s, maze, dir);
		}
	}

	for (i = 0; i < DIR_SIZE; i++){
		if (maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].status != WALL
				&& maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited != VISITED){
			maze[s->point[s->top].x][s->point[s->top].y].visited = UNVISITED;
			Stack_Pop(s);
			return;
		}
	}

	if (maze[s->point[s->top].x][s->point[s->top].y - 1].status == ROAD && maze[s->point[s->top].x][s->point[s->top].y - 1].visited == UNVISITED)
		maze[s->point[s->top].x][s->point[s->top].y].visited = UNVISITED;

	maze[s->point[s->top].x][s->point[s->top].y].visited = BARRIER;
	Stack_Pop(s);
	return;
}


数据结构与算法学习之路:迷宫问题——回溯思想找出所有路径