目录

二维数组寻找最短路径

临阵磨枪,不亮也光。

写一个路径搜索算法。

场景:给你一个由二维数组形成的平面,平面中的方格是可以走的路,方格中1代表障碍物,0代表没有障碍的路,找到此平面中,从坐标(0, 0),走到(9,9),有没有顺利通过的路,如果有,返回最短的路径

0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 1 0 1 0 0 1
1 0 0 1 0 1 1 1 1 1 0
2 0 0 0 0 1 1 0 0 0 0
3 1 0 0 0 1 1 1 1 1 0
4 0 0 1 0 0 0 0 1 0 0
5 1 0 0 1 1 0 0 0 1 0
6 0 1 0 0 0 1 1 0 1 0
7 0 0 0 1 0 0 1 0 1 0
8 0 0 1 1 1 0 0 0 0 0
9 1 1 1 0 0 0 0 0 1 0

这是一个10x10的方格,作为一个正常人,通过数,确实可以数出来,有多少条路,那条路最短。但是如果给定的是100x100, 1000000*1000000呢

开发环境

1
2
语言: golang:1.16.6
编辑器: goland

代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
package main

import (
	"fmt"
	"sort"
	"time"
)

func Min(list [][]int)[][]int{
	var result [][][]int
	var line [][]int
	var dfs func(list [][]int, current []int)
	dfs = func(list [][]int, current []int) {

		// 获取当前位置xy轴
		y, x := current[0], current[1]

		// 出界返回, 继续下一个方向
		if x >= len(list[0]) || x < 0 || y >= len(list) || y < 0 || list[y][x] == 1  {
			return
		}

		// 记录已走过的路,以免走回头路
		list[y][x] = 1

		// 将当前坐标添加到线路切片中
		line = append(line, []int{y, x})

		// 记录当前线路状态,在此位置可能还有其他方向可以走
		tmp := line

		// 可视化
		//for _, v := range list{
		//	fmt.Println(v)
		//}
		//fmt.Println()
		//time.Sleep(time.Second)


		// 如果到达终点
		if x == len(list[0])-1 && y == len(list)-1{
			// 还原已走过的路
			list[y][x] = 0

			// 必须拷贝,不然前面修改的路线位置无法获取
			n := make([][]int, len(line))
			copy(n, line)

			// 记录成功结果线路
			result = append(result, n)
			return
		}

		// 向右走
		dfs(list, []int{y, x+1})
		line = tmp // 还原已走过的路
		// 向下走
		dfs(list, []int{y+1, x})
		line = tmp // 还原已走过的路
		// 向左走
		dfs(list, []int{y, x-1})
		line = tmp // 还原已走过的路
		// 向上走
		dfs(list, []int{y-1, x})

		// 还原已走过的路
		list[y][x] = 0
	}

	// 开始递归
	dfs(list, []int{0, 0})

	// 如果没有成功走到终点的线路,返回空
	if len(result) == 0{
		return nil
	}

	// 最短路径
	sort.Slice(result, func(i, j int) bool {
		return len(result[i]) < len(result[j])
	})
	fmt.Printf("共有线路: %d条\n", len(result))
	return result[0]

	// 共有几种走法
	// return len(result)

}



func main() {
	fmt.Println(time.Now())
	list := [][]int{{0, 0, 0, 0, 1, 0, 1, 0, 0, 1},
		            {0, 0, 1, 0, 1, 1, 1, 1, 1, 0},
					{0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
					{1, 0, 0, 0, 1, 1, 1, 1, 1, 0},
					{0, 0, 1, 0, 0, 0, 0, 1, 0, 0},
					{1, 0, 0, 1, 1, 0, 0, 0, 1, 0},
					{0, 1, 0, 0, 0, 1, 1, 0, 1, 0},
					{0, 0, 0, 1, 0, 0, 1, 0, 1, 0},
					{0, 0, 1, 1, 1, 0, 0, 0, 0, 0},
					{1, 1, 1, 0, 0, 0, 0, 0, 1, 0},
		}

	 fmt.Println(Min(list))
	fmt.Println(time.Now())
}

执行结果

1
2
3
4
2022-05-30 15:29:22.861003 +0800 CST m=+0.002519301
共有线路: 136条
[[0 0] [0 1] [1 1] [2 1] [2 2] [2 3] [3 3] [4 3] [4 4] [4 5] [5 5] [5 6] [5 7] [6 7] [7 7] [8 7] [8 8] [8 9] [9 9]]
2022-05-30 15:29:22.8713061 +0800 CST m=+0.012822401

可以看到,10*10的地图,共搜索到136条线路,并且给出了最短线路,用时才0.01秒。

根据提供的地图,可能同时存在多条最短的路径,不过得到所有路线之后,可以继续其他的逻辑,可以由需求决定,该如何处理。

难道这就是高德地图、百度地图的终极算法吗