回溯算法:
所谓“回溯”,其实就是回退、倒退的意思,利用回溯算法来查找正确答案,一旦不是正确答案的话就会直接进行“回溯”。以图中的A--->K的路径,
回溯算法查找从 A 到 K 路线的过程是:
- 从 A 出发,先选择 A-B 路线;继续从 B 出发,先选择 B-C 路线;到达 C 点后发现无路可选,表明当前路线无法达到 K 点,该算法会立刻回退到上一个节点,也就是 B 点;
- 从 B 点出发,选择 B-D 路线,达到 D 点后发现无法到达 K 点,该算法再回退到 B 点;
- 从 B 点出发已经没有新的线路可以选择,该算法再次回退到 A 点,选择新的 A-E 路线;
- 继续以同样的方式测试 A-E-F-G、A-E-F-H、A-E-J-I 这 3 条线路后,最终找到 A-E-J-K 路线。
迷宫问题:
迷宫问题指的是:在给定区域内,找到一条甚至所有从某个位置到另一个位置的移动路线。就可以采用回溯算法解决,即从起点开始,采用不断“回溯”的方式逐一试探所有的移动路线,最终找到可以到达终点的路线。
回溯算法解决迷宫问题思路:
1)首先,从起始位置开始,会有四个方向(上下左右四个方向),进行判断能否向着四个方向进行移动
2)然后选择一个方向进行移动,将行走过的位置记为“Y”,如果这个位置就是终点位置的话就表示找到了一条通向终点的路线(这样的话打印出来的就是Y就表示一条路线)。如果不是的话,那么此位置又会有四个方向可以选择移动,
3)如果四个方向都无法移动的话(将该位置标记为1),那么就回溯上一个位置,继续判断其他方向是否能有移动
4)重复2,3步,要么会找到终点的位置,要么会回溯到起点位置,表明所有位置都已经判断完毕了
在程序中我们运用不同的字符来表示迷宫中的不同区域,1表示可以行走的位置,0表示黑色墙壁障碍,这样的话迷宫就可以用矩阵来表示
1 0 1 1 1
1 1 1 0 1
1 0 0 1 1
1 0 0 1 0
1 0 0 1 1
迷宫问题伪代码:
输入 maze[ROW][COL] //输入迷宫地图,0 表示黑色区域,1 表示可行走区域 //(row,col) 表示起点,(outrow,outcol)表示终点 maze_puzzle(maze,row,col,outrow,outcol): //回溯过程中,行走的每一区域都设为 Y,表示已经进行了判断 maze[row][col] <- 'Y' //如果行走至终点,表明有从起点到终点的路线 if row == outrow && col == outcol: Print maze // 输出行走路线 return //判断是否可以向上移动 if canMove(maze,row-1,col): maze_puzzle(maze,row-1,col,outrow,outcol) //判断是否可以向左移动 if canMove(maze,row,col-1): maze_puzzle(maze,row,col-1,outrow,outcol) //判断是否可以向下移动 if canmove(maze,row+1,col): maze_puzzle(maze,row+1,col,outrow,outcol) //判断是否可以向右移动 if canmove(maze,row,col+1): maze_puzzle(maze,row,col+1,outrow,outcol)
迷宫代码实现:
//迷宫问题,并不涉及最端路径问题
#include <stdio.h>
//typedef enum { false, true } bool;
#define ROW 5
#define COL 5
//设置一个5*5的二维矩阵
bool find = false;
//进行判断能否进行相应方向的移动
bool can_move(char maze[ROW][COL], int row, int col)
{
//如果目标位于地图区域,同时不是障碍,且没有走过,则返回true,否则返回false
return row >= 0 && row <= ROW - 1 && col >= 0 && col <= COL - 1 &&
maze[row][col] != '0' && maze[row][col] != 'Y';
}
//进行打印最后的路径
void maze_print(char maze[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%c ", maze[i][j]);
}
printf("\n");
}
}
//(row,col)表示开始位置,(outrow,outcol)表示中间位置
void maze_puzzle(char maze[ROW][COL], int row, int col, int outrow, int outcol)
{
maze[row][col] = 'Y';
//进行判断什么时候进行结束递归
if (row == outrow && col == outcol)
{
find = true;
printf("find the final point\n");
maze_print(maze);
return;
}
//查看能否向上移动
if (can_move(maze, row-1, col))
{
maze_puzzle(maze,row-1,col,outrow,outcol);
//如果行走不通的话就将该位置标记为1,然后回溯
maze[row - 1][col] = '1';
}
//查看能否向右移动
if (can_move(maze, row, col + 1))
{
maze_puzzle(maze,row,col +1,outrow,outcol);
//行走不通就将该位置标记为1,然后回溯
maze[row][col+1] = '1';
}
//查看能否向下移动
if (can_move(maze, row + 1, col))
{
maze_puzzle(maze, row + 1, col, outrow, outcol);
//行走不通的话就将该位置标记为1,然后回溯
maze[row + 1][col] = '1';
}
//查看能否向左移动
if (can_move(maze, row, col - 1))
{
maze_puzzle(maze, row, col - 1, outrow, outcol);
}
maze[row][col - 1] = '1';
}
int main()
{
//设置好迷宫的数组,1表示可以行走的路径,0表示障碍
char maze[ROW][COL] = { {1,0,1,1,1},
{1,1,1,0,1},
{1,0,0,1,1},
{1,0,0,1,0},
{1,0,0,1,1} };
//进行判断路径
maze_puzzle(maze, 0, 0, ROW - 1, COL - 1);
if (find == false)
{
printf("can't find the way\n");
}
return 0;
}
执行结果:
Y 0 Y Y Y
Y Y Y 0 Y
1 0 0 Y Y
1 0 0 Y 0
1 00 Y Y
注意:此回溯算法解决迷宫问题并不涉及解决迷宫问题的最短路径问题。