zoukankan      html  css  js  c++  java
  • 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 那么说明图中存在 负权回路

  • 相关阅读:
    路飞学城Python-Day142
    路飞学城Python-Day141
    路飞学城Python-Day140
    路飞学城Python-Day136
    路飞学城Python-Day137
    路飞学城Python-Day117
    java基础知识总结
    Maven
    MySql实现分页查询
    js中的正则表达式入门
  • 原文地址:https://www.cnblogs.com/sfzyk/p/9314026.html
Copyright © 2011-2022 走看看