【算法】回溯算法解决迷宫问题

// 迷宫问题指的是:在给定区域内,找到一条甚至所有从某个位置到另一个位置的移动路线。
// 迷宫问题就可以采用回溯算法解决,即从起点开始,采用不断“回溯”的方式逐一试探所有的移动路线,最终找到可以到达终点的路线

// 以图 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("未找到可行线路")
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值