首先我们了解一下回溯法。
回溯法:对于一个包括有很多个节点,每个节点由若干个搜索分支的问题,把原问题分解为若干个子问题求解的算法;当搜索到某个节点发现无法再继续搜索下去时,就让搜索过程回溯(回退)到该节点的前一个结点,继续搜索该节点外的其他尚未搜索的分支;如果发现该节点无法再搜索下去,就让搜索过程回溯到这个节点的前一结点继续这样的搜索过程;这样的搜索过程一直进行到搜索到问题的解或者搜索完了全部可搜索分支没有解存在为止。
迷宫:
0 0 0 0 0 0
0 1 1 1 0 0
0 1 0 1 0 0
0 1 0 1 0 0
0 1 1 1 1 1
0 1 0 0 0 0
思路:
1.传送迷宫地图的入口坐标,判断入口坐标是否正确。
2.开始走迷宫,
将当前坐标(Cur)入栈,准备往某个方向走
上:上走,先判断上面是否可以走的通,可以就往上走,并修改下一步值为当前值+1;递归当前坐标,一直往前走,直到不可以往上走
左:上走不通左走,判断是否可以走,可以就往左走,并修改下一步值为当前值+1;递归当前坐标,一直往左走,直到不可以往左走
右:左走不通右走,判断是否可以走,可以就往右走,并修改下一步值为当前值+1;递归当前坐标,一直往右走,直到不可以往右走,
下:右走不通下走,判断是否可以走,可以就往下走,并修改下一步值为当前值+1;递归当前坐标,一直往下走,直到不可以往下走,
3.重复过程2
4.找到出口,不要着急退出可能有两个出口,所以要退回去找是否还有别的出口,
5.输出最短路径
主要用了递归的思想,走过的路便不会重复走。并且走过之后所有的值都会变化为>1的数
#define ROW 6
#define COL 6
#define MAX 20
typedef int DataType;
typedef struct postion
{
int _x;
int _y;
}position;
typedef position SDataType;
typedef struct Stack
{
SDataType array[MAX];
int top;
}Stack;
typedef struct Maze
{
DataType _map[ROW][COL];
}Maze;
void InitMaze(int map[ROW][COL],Maze* m);//初始化
void PrintfMaze(Maze* m);//打印迷宫
void PassMaze(Maze* m, SDataType enter);//走迷宫
因为要给栈中压入坐标类型的而数据,所以需要创建一个坐标类型的结构体,并用坐标类型定义栈的类型。
void InitMaze(int map[ROW][COL],Maze* m)//初始化
{
int i = 0;
int j = 0;
assert(m);
for (; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
m->_map[i][j] = map[i][j];
}
}
}
void PrintfMaze(Maze* m)//打印迷宫
{
int i = 0;
int j = 0;
assert(m);
for (; i < ROW; i++)
{
for (j = 0; j < COL; j++)
printf("%3d", m->_map[i][j]);
printf("\n");
}
}
int IsValid(SDataType enter)//判断入口是否正确
{
if (0 == enter._x || 0 == enter._y || ROW - 1 == enter._x || COL - 1 == enter._y)
return 1;
return 0;
}
int IsExit(SDataType Cur,SDataType enter)//判断是否为出口
{
if ((0 == Cur._x || 0 == Cur._y || ROW - 1 == Cur._x || COL - 1 == Cur._y) && (Cur._x != enter._x || Cur._y != enter._y))
return 1;
return 0;
}
int IsPass(Maze* m, SDataType next)//检测此路是否通
{
assert(m);
if (next._x < ROW && next._y < COL && next._x >= 0 && next._y >= 0)
{
if (1 == m->_map[next._x][next._y])
return 1;
}
return 0;
}
void SaveShortPath(Stack* Path, Stack* ShortPath)//保存最短路径
{
int i = 0;
for (; i < StackSize(Path); i++)
ShortPath->array[i] = Path->array[i];
ShortPath->top = Path->top;
}
void _GetPassMaze(Maze* m, SDataType enter, SDataType Cur, Stack* Path, Stack* ShortPath)//递归
{
SDataType next;
if (!StackSize(Path))//如果栈为空,说明刚开始将当前位置变为2入栈
m->_map[enter._x][enter._y] = 2;
if (IsExit(Cur, enter))//判断是否是出口
{
StackPush(Path, Cur);
if (!StackSize(ShortPath) || StackSize(Path) < StackSize(ShortPath))
SaveShortPath(Path, ShortPath);//保存最短路径
StackPop(Path);
return;
}
StackPush(Path, Cur);
//上
next = Cur;
next._x -= 1;
if (IsPass(m, next, Cur))//判断此路是否可以走
{
m->_map[next._x][next._y] = m->_map[Cur._x][Cur._y] + 1;
_GetPassMaze(m, enter, next, Path, ShortPath);
}
//左
next = Cur;
next._y -= 1;
if (IsPass(m, next, Cur))//判断此路是否可以走
{
m->_map[next._x][next._y] = m->_map[Cur._x][Cur._y] + 1;
_GetPassMaze(m, enter, next, Path, ShortPath);
}
//右
next = Cur;
next._y += 1;
if (IsPass(m, next, Cur))//判断此路是否可以走
{
m->_map[next._x][next._y] = m->_map[Cur._x][Cur._y] + 1;
_GetPassMaze(m, enter, next, Path, ShortPath);
}
//下
next = Cur;
next._x += 1;
if (IsPass(m, next, Cur))//判断此路是否可以走
{
m->_map[next._x][next._y] = m->_map[Cur._x][Cur._y] + 1;
_GetPassMaze(m, enter, next, Path, ShortPath);
}
StackPop(Path);
}
void PassMaze(Maze* m, SDataType enter)
{
Stack ShortPath;
Stack Path;
assert(m);
InitStack(&Path);
InitStack(&ShortPath);
if (!IsValid(enter))
return;
_GetPassMaze(m, enter, enter, &Path, &ShortPath);//调用递归函数,走迷宫
}
void Test()//测试函数
{
SDataType enter;
Maze m;
int map[ROW][COL] = { 0,0,0,0,0,0,
0,0,1,0,0,0,
0,0,1,0,0,0,
0,0,1,0,0,0,
0,0,1,1,1,1,
0,0,1,0,0,0 };
InitMaze(map,&m);
PrintfMaze(&m);
printf("\n");
enter._x = 5;
enter._y = 2;
PassMaze(&m, enter);
PrintfMaze(&m);
}
上面这段代码有几个栈的基本函数没有给,可以自己完善调用。