// 迷宫问题指的是:在给定区域内,找到一条甚至所有从某个位置到另一个位置的移动路线。
// 迷宫问题就可以采用回溯算法解决,即从起点开始,采用不断“回溯”的方式逐一试探所有的移动路线,最终找到可以到达终点的路线
// 以图 1 所示的迷宫为例,回溯算法解决此问题的具体思路是:
// 从当前位置开始,分别判断是否可以向 4 个方向(上、下、左、右)移动:
// 选择一个方向并移动到下个位置。判断此位置是否为终点,如果是就表示找到了一条移动路线;如果不是,
// 在当前位置继续判断是否可以向 4 个方向移动;
// 如果 4 个方向都无法移动,则回退至之前的位置,继续判断其它的方向;
// 重复 2、3 步,最终要么成功找到可行的路线,要么回退至起点位置,表明所有的路线都已经判断完毕。
// 程序中,我们可以用特殊的字符表示迷宫中的不同区域。例如,用 1 表示可以移动的白色区域,用 0 表示不能移动的黑色区域,
// 图 1 的迷宫可以用如下的 0-1 矩阵来表示:
// 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
package main
import "fmt"
var maze [][]int = [][]int{
{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}}
var flag int = 666
var result bool = false
func printMaze(m [][]int) {
for i := 0; i < len(m); i++ {
for j := 0; j < len(m); j++ {
fmt.Printf("%#v \t", m[i][j])
}
fmt.Println()
}
}
func move(m [][]int, r int, c int) (b bool) {
if r >= 0 && r <= len(m)-1 && c >= 0 && c <= len(m)-1 && m[r][c] != 0 && m[r][c] != flag {
return true
} else {
return false
}
}
// (r,c)表示起点,(or,oc)表示终点
func maze_puzzle(m [][] int, r int, c int, or int, oc int) {
// 将各个走过的区域标记
m[r][c] = flag
//fmt.Printf("m(%d,%d)\n", r, c)
//printMaze(m)
// 尝试向上移动
if move(m, r-1, c) {
//fmt.Println("向上")
maze_puzzle(m, r-1, c, or, oc)
//如果程序不结束,表明此路不通,恢复改区域的标记
maze[r-1][c] = 1
}
// 尝试向下移动
if move(m, r+1, c) {
//fmt.Println("向下")
maze_puzzle(m, r+1, c, or, oc)
//如果程序不结束,表明此路不通,恢复改区域的标记
maze[r+1][c] = 1
}
// 尝试向左移动
if move(m, r, c-1) {
//fmt.Println("向左")
maze_puzzle(m, r, c-1, or, oc)
//如果程序不结束,表明此路不通,恢复改区域的标记
maze[r][c-1] = 1
}
// 尝试向右移动
if move(m, r, c+1) {
//fmt.Println("向右边")
maze_puzzle(m, r, c+1, or, oc)
//如果程序不结束,表明此路不通,恢复改区域的标记
maze[r][c+1] = 1
}
// 如果行走至终点,表明有从起点到终点的路线
if r == or && c == oc {
result = true
fmt.Printf("成功走出迷宫,标志位%d所在位置组成的就是路线图:\n", flag)
printMaze(maze)
return
}
}
func main() {
maze_puzzle(maze, 0, 0, len(maze)-1, len(maze)-1)
if result == false {
fmt.Println("未找到可行线路")
}
}
【算法】回溯算法解决迷宫问题
最新推荐文章于 2022-11-12 20:13:41 发布