要求
从迷宫的起点走到终点,其中0表示可走,1表示不可走
a) b)
c)
d)
思路
1、给每个点标坐标,按逆时针方向探索可行点,并将其入队。
2、首先探索(0, 0)附近可行点,只有(1, 0),因此(1, 0)入队
3、(1, 0)出队,探索(1, 0)附近可行点,有(2, 0)和(1, 1)2个点,这2个点入队
4、(2, 0)出队,探索附近可行点,并将可行点加入队列
5、(1, 1)出队,探索附近可行点,并将可行点加入队列
6、依次类推,直至探索到终点(5, 4)为止,或者探索到队列为空,说明不存在路径可达起点到终点。
7、为每一个坐标标上所走步数,从终点往起点推,每一个点附近只有一个上一个步数,因此可以得到最终路径
以上思路实际上一个广度优先算法。
go实现
package main
import (
"fmt"
)
/**
迷宫如下:6行5列,0代表可走,1代表不可走,只能上下左右走,不能斜着走
0 1 0 0 0
0 0 0 1 0
0 1 0 1 0
1 1 1 0 0
0 1 0 0 1
0 1 0 0 0
坐上角开始,右下角结束。要求走出最短路径
*/
type point struct {
i, j int
}
//每个点有4个方向,上左下右
var dirs = [4]point{
{-1, 0},
{0, -1},
{1, 0},
{0, 1},
}
func (p point) add(r point) point {
return point{p.i + r.i, p.j + r.j}
}
//返回值int代表当前点step,bool表示是否越界(坐标超过grid)
func (p point) at(grid [][]int) (int, bool) {
if p.i < 0 || p.i >= len(grid) {
return 0, false
}
if p.j < 0 || p.j >= len(grid[p.i]) {
return 0, false
}
return grid[p.i][p.j], true
}
func walk(mazi [][]int, start, end point) [][]int {
steps := make([][]int, len(mazi)) //走到该坐标所需步数数组
for i := range steps {
steps[i] = make([]int, len(mazi[0]))
}
//队列
Q := []point{start}
for len(Q) > 0 {
cur := Q[0]
Q = Q[1:]
if cur == end {//找到终点
break
}
//发现当前点的四个方向
for _, dir := range dirs{
next := cur.add(dir)
//探索可行节点
//1.next不是墙,即值=0
//2.next的没走过,即step为0
//3.next != start
val, ok := next.at(mazi)
if !ok || val == 1 { //剔除不能走的情况
continue
}
val, ok = next.at(steps)
if !ok || val != 0 { //剔除不能走的情况
continue
}
if next == start {
continue
}
//更新步数
curSteps, _ := cur.at(steps)
steps[next.i][next.j] = curSteps + 1
//可行点入队
Q = append(Q, next)
}
}
return steps
}
func findPath(steps [][]int) []point {
start := point{0,0}
poi := point{len(steps)-1, len(steps[0])-1}
value := steps[len(steps)-1][len(steps[0])-1]
var list = []point{poi}
for poi != start {
for _, dir := range dirs {
last := poi.add(dir)
//判断是否越界
if _, ok := last.at(steps); ok {
if steps[last.i][last.j] == (value - 1) {
list = append(list, last)
poi = last
value --
break
}
}
}
}
return list
}
func main() {
maze := [][]int{
{0, 1, 0, 0, 0},
{0, 0, 0, 1, 0},
{0, 1, 0, 1, 0},
{1, 1, 1, 0, 0},
{0, 1, 0, 0, 1},
{0, 1, 0, 0, 0}}
steps := walk(maze, point{0, 0}, point{len(maze)-1, len(maze[0])-1})
fmt.Println("迷宫步数图:")
for _, row := range steps {
for _, val := range row {
fmt.Printf("%3d", val)
}
fmt.Println()
}
fmt.Println("最短需要走的步数:", steps[len(maze)-1][len(maze[0])-1])
fmt.Print("最短路径坐标为:")
paths := findPath(steps)
for i := len(paths) -1; i >= 0; i-- {
fmt.Printf("(%d, %d) ", paths[i].i, paths[i].j)
}
}
/*
迷宫步数图:
0 0 4 5 6
1 2 3 0 7
2 0 4 0 8
0 0 0 10 9
0 0 12 11 0
0 0 13 12 13
*/