算法编程题-访问所有节点的最短路径

原题描述

访问所有节点的最短路径。原题为在一张图中,有n个节点,编号为从0到n-1,这个图本身是一个无向连通图,要求一条路径,经过所有节点。注意,每一个节点和每一条边都可以被访问多次。值得关注的一点是图中节点数量不超过12。这个应该是解题的一个关键,不超过12意味着可以用状态压缩来保存当前的节点访问状态,即用12个bit,从低到高,分别表示节点0到节点n-1的访问状态,节点对应位为1,则表示该节点已被访问。

广度优先搜索

思路简述

很容易想到的一种做法就是广度优先搜索,求最短路径什么的,如果图各个边的权重是完全相同的,就可以使用广度优先搜索。广度优先搜索,可以使用双端队列来实现。在本题中,搜索的状态为当前访问的节点和历史访问状态(状态压缩)以及当前访问路径的长度。在实现上,需要用一个哈希表记录已经搜索过的状态,避免重复搜索。

代码

func shortestPathLength(graph [][]int) int {
   
   
    n := len(graph)
	deque := list.New()
	visited := make(map[string]struct{
   
   }, 0)
	// 加入以各个点开始的初始状态
	for i := 0; i < n; i++ {
   
   
		deque.PushBack([]int{
   
   i, 1 << i, 0})  // 初始状态
		visited[fmt.Sprintf("%d-%d", i, 1 << i)] = struct{
   
   }{
   
   }
	}
	for deque.Len() != 0 {
   
   
		cur := deque.Remove(deque.Front()).([]int)
		curPos, state, pathLen := cur[0], cur[1], cur[2]
		if state == (1 << n) - 1 {
   
     // 状态压缩,此时相当于每一个点都被访问了
			return pathLen   // bfs, 所以可以直接返回答案
		}
		// 访问当前节点的所有邻居节点
		for _, adj := range graph[curPos] {
   
   
			newState := state | (1 << adj)
			if _, ok := visited[fmt.Sprintf("%d-%d", adj, newState)]; ok {
   
   
				continue
			}
			deque.PushBack([]int{
   
   adj, newState, pathLen + 1})
			visited[fmt.Sprintf("%d-%d", adj, newState)] = struct{
   
   }{
   
   }
		}
	}
	return -1
}

复杂度分析

  • 时间复杂度: O ( n 2 ∗ 2 n ) O(n^2* 2^n) O(n22n),由于有哈希表保证在广度优先搜索中不会重复搜索,而状态数一共是 n ∗ 2 n n * 2 ^n n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值