迷宫问题最主要用的就是回溯法,首先我们来了解一下回溯法的概念
回溯法:对一个包括有很多结点,每个结点有若干个搜索分支的问题,把原问题分解为若干个子问题求解的算法;当搜索到某个结点发现无法再继续搜索下去时,就让搜索过程回溯(后退)到该节点的前一个结点,继续搜索该结点外的其他尚未搜索的分支;如果发现该结点无法再搜索下去,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一直进行到搜索到问题的解或者搜索完了全部可搜索分支没有解存在为止。
迷宫问题分为简单迷宫,多通路迷宫:通路间不带环,多通路迷宫:通路间带环
简单迷宫
多通路迷宫:通路间不带环
多通路迷宫:通路间带环
下面我们来实现一下多通路迷宫:通路间带环
思路:我们借助一个栈,然后把入口点定义为2,让接下来走过的地方依次加1,走到迷宫出口的时候,然后出栈(也就是回溯),一步一步的出栈,然后探索看还有没有其他的路可以走,当下一步位置的值是1或者下一个位置减去1大于当前位置,就走这个位置,然后继续探索。
最短路径:设置一个全局的变量来记录最短路径的长度,第一次到达终点,把路径长度赋值给全局变量,在以后的回溯中遇到终点则比较,如果小于全局变量的值,则该变为最短路径。
代码实现:
Maze.h
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <string.h>
#define N 6
typedef struct Pos
{
int row;
int col;
}Pos;
int MazeCheckAccess(Pos next, Pos cur);
void MazeGetPath(Pos entry,Pos exit);
//void MazeGetPathR(Pos entry);
//Stack shortPath;
//void MazeGetShortPath(Pos entry, Stack* path);
typedef Pos DataType;
#define S 10
typedef struct Stack
{
DataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
void StackInit(Stack* ps);
void StackDestory(Stack* ps);
void StackPush(Stack* ps, DataType x);
void StackPop(Stack* ps);
DataType StackTop(Stack* ps);
int StackEmpty(Stack* ps);
int StackSize(Stack* ps);
void TestStack();
Maze.c
#include"Maze.h"
int maze[N][N] =
{
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 },
};
int count = 0;
int MazeCheckAccess(Pos next, Pos cur) //判断下一步能不能走
{
if (((next.row >= 0 && next.row < N) &&( next.col >= 0 && next.col<N) )&&
((maze[next.row][next.col] == 1) || (maze[next.row][next.col] - 1 > maze[cur.row][cur.col])))
{
return 1;
}
else
{
return 0;
}
}
void MazeGetPath(Pos entry, Pos exit)
{
Stack path;
StackInit(&path);
StackPush(&path, entry);
maze[entry.row][entry.col] = 2;
while (StackEmpty(&path)!= 0)
{
Pos cur = StackTop(&path);
if (cur.col == N - 1)
{
if (StackSize(&path) < count || count == 0)
{
count = StackSize(&path);
}
}
Pos next;
//上
next = cur;
next.row -= 1;
if (MazeCheckAccess(next, cur))
{
maze[next.row][next.col] = maze[cur.row][cur.col] + 1;
StackPush(&path, next);
continue;
}
//下
next = cur;
next.row += 1;
if (MazeCheckAccess(next, cur))
{
maze[next.row][next.col] = maze[cur.row][cur.col] + 1;
StackPush(&path, next);
continue;
}
//左
next = cur;
next.col -= 1;
if (MazeCheckAccess(next, cur))
{
maze[next.row][next.col] = maze[cur.row][cur.col] + 1;
StackPush(&path, next);
continue;
}
//右
next = cur;
next.col += 1;
if (MazeCheckAccess(next, cur))
{
maze[next.row][next.col] = maze[cur.row][cur.col] + 1;
StackPush(&path, next);
continue;
}
//回溯
StackPop(&path);
}
}
int main()
{
int i = 0;
int j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%2d",maze[i][j]);
}
printf("\n");
}
Pos entry, exit;//迷宫入口 出口
entry.row = 5;
entry.col = 2;
exit.row = 4;
exit.col = 5;
MazeGetPath(entry, exit);
printf("最短路径为:%d\n", count);
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%2d", maze[i][j]);
}
printf("\n");
}
return 0;
}
stack.c
#include "Maze.h"
void StackInit(Stack* ps)
{
assert(ps);
ps->_a = (DataType*)malloc(sizeof(DataType)*S);
ps->_top = 0;
ps->_capacity = S;
}
void StackDestory(Stack* ps)
{
assert(ps);
ps->_a = NULL;
ps->_top = 0;
ps->_capacity = 0;
free(ps);
ps = NULL;
}
void StackPush(Stack* ps, DataType x)
{
DataType* cur;
assert(ps);
if (ps->_top == ps->_capacity)
{
cur = (DataType*)realloc(ps->_a, sizeof(DataType) * 2 * ps->_capacity);
if (cur != NULL)
{
ps->_a = cur;
}
ps->_capacity = 2 * ps->_capacity;
}
ps->_a[ps->_top] = x;
ps->_top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->_top > 0);
ps->_top--;
}
DataType StackTop(Stack* ps)
{
assert(ps);
assert(ps->_top > 0);
return ps->_a[ps->_top - 1];
}
int StackEmpty(Stack* ps)//空0 非空1
{
assert(ps);
return ps->_top == 0 ? 0 : 1;
}
int StackSize(Stack* ps)
{
assert(ps);
return ps->_top;
}
运行结果如下: