leetcode 847. Shortest Path Visiting All Nodes 无向连通图遍历最短路径

设计最短路径 用bfs 天然带最短路径
每一个状态是 当前的阶段 和已经访问过的节点
下面是正确但是超时的代码

class Solution:
    def shortestPathLength(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: int
        """
        N=len(graph)
        
        Q=collections.deque([(1 << x, x) for x in range(N)])
        D=collections.defaultdict(lambda:N*N)
        
        for i in range(N):
            D[1<<i,i]=0
            
        
        mask=0
        #listr= [i for i in range(N)]
        #random.shuffle(listr)
        
        for i in range(N):
            mask=mask|1<<i
 
        
        while Q:
            a,h=Q.popleft()
            d=D[a,h]
            
            
            if(a==mask):
            
                return d

            for child in graph[h]:
 
                new_a=a |(1<<child)

                Q.append((new_a,child))
                
                D[new_a,child]=min(d+1,D[new_a,child])

下面的代码稍微有优化,但是这种优化是非常好的。(值得思考的优化)

归根结底是因为没有考虑好一个状态是指什么。
在这里一个状态指的是, 以前便利过的节点 和 当前的节点。
有了这个节点状态
就不用把(到达这个节点的距离作为节点的一部分加入节点中,加入会引起性能损失)

到达这个节点的距离 单独存入一个数组中做优化 如果同一个状态后来的距离反而更长 那就丢弃。

class Solution:
    def shortestPathLength(self, graph):
        N=len(graph)
        Q=collections.deque([(1 << x, x) for x in range(N)])
        D=collections.defaultdict(lambda:N*N)
        
        for i in range(N):
            D[1<<i,i]=0
            
        mask=0
        for i in range(N):
            mask=mask|1<<i
 
        
        while Q:
            cover,head=Q.popleft()
            d=D[cover,head]
            
            if(cover==mask):
                return d

            for child in graph[head]:
                
                new_a=cover |(1<<child)
                
                if(d+1<D[new_a,child]):
                    D[new_a,child]=d+1
                    Q.append((new_a,child))                

动态规划算法
一个数组
state[ cover ][ head ] 表示当前状态所能达到的最小距离
head 维数的遍历顺序随意
cover 的遍历循序是从小到大

因为 new_cover=cover| child 这样的话内在隐含着一个内在的顺序

这样看来 这个题目有意卡掉了那些没有注意到这种顺序的方法

"relaxation step" (for those familiar with the Bellman-Ford algorithm)

复习 Bellman-Ford algorithm

O(V*E)
1 初始化

2 n-1 次循环 每一个循环遍历每一个边 做 relaxtion step

3 额外判断是否每一条边都 存在优化空间

第i次循环 实际上是在寻找 单源最短路径
如果n-1 次循环后还能做 relaxtion step 那么说明图中存在 负权回路

猜你喜欢

转载自www.cnblogs.com/sfzyk/p/9314026.html