Quantcast
Channel: 书影 - Entries for the tag leetcode
Viewing all articles
Browse latest Browse all 559

[LeetCode]Shortest Path Visiting All Nodes

$
0
0

题目描述:

LeetCode 847. Shortest Path Visiting All Nodes

An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1) is given as graph.

graph.length = N, and j != i is in the list graph[i] exactly once, if and only if nodes i and j are connected.

Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.

    Example 1:

    Input: [[1,2,3],[0],[0],[0]]Output: 4Explanation: One possible path is [1,0,2,0,3]

    Example 2:

    Input: [[1],[0,2,4],[1,3,4],[2],[1,2]]Output: 4Explanation: One possible path is [0,1,4,2,3]

    Note:

    1. 1 <= graph.length <= 12
    2. 0 <= graph[i].length < graph.length

    题目大意:

    给定无向图graph,求可以遍历所有点的最短路径

    解题思路:

    Floyd + 动态规划(Dynamic Programming)

    时间复杂度 O(2^n * n^2)

    利用Floyd求出每对顶点i, j之间的最短距离,记为dp[i][j],代价为O(N^3)
    
    利用status[s][i]记录:状态为s,当前所在节点为i时的最小路径长度
    
    状态s是二进制,表示各节点是否被访问过,1表示已访问,0表示未访问
    
    状态转移方程:
    
    status[ns][j] = min(status[ns][j], status[s][i] + dp[i][j])
    
    其中ns表示从状态s的i点出发到达j点时的新状态

    Python代码:

    class Solution(object):
        def shortestPathLength(self, graph):
            """
            :type graph: List[List[int]]
            :rtype: int
            """
            INF = 0x7FFFFFFF
            N = len(graph)
            dp = [[INF] * N for x in range(N)]
            for i, e in enumerate(graph):
                dp[i][i] = 0
                for j in e:
                    dp[i][j] = dp[j][i] = 1
            for z in range(N):
                for x in range(N):
                    for y in range(N):
                        dp[x][y] = min(dp[x][y], dp[x][z] + dp[z][y])
    
            status = {(0, i) : 0 for i in range(N)}        
            for s in range(1 << N):
                for i in range(N):
                    if (s, i) not in status: continue
                    v = status[(s, i)]
                    for j in range(N):
                        ns = s | (1 << j)
                        if status.get((ns, j), INF) > v + dp[i][j]:
                            status[(ns, j)] = v + dp[i][j]
            return min(status[((1 << N) - 1, i)] for i in range(N))

    比赛时只想到了Floyd + DFS + 剪枝的解法

    由于该解法的时间复杂度为O(N!),因此TLE

    Python代码:

    class Solution(object):
        def shortestPathLength(self, graph):
            """
            :type graph: List[List[int]]
            :rtype: int
            """
            INF = 0x7FFFFFFF
            N = len(graph)
            dp = [[INF] * N for x in range(N)]
            for i, e in enumerate(graph):
                dp[i][i] = 0
                for j in e:
                    dp[i][j] = dp[j][i] = 1
            for z in range(N):
                for x in range(N):
                    for y in range(N):
                        dp[x][y] = min(dp[x][y], dp[x][z] + dp[z][y])
    
            self.best = INF
            visits = set()
            def dfs(s, c, t):
                if t >= self.best: return
                if c == N:
                    self.best = min(self.best, t)
                    return
                for n in range(N):
                    if n in visits: continue
                    visits.add(n)
                    dfs(n, c + 1, t + dp[s][n])
                    visits.remove(n)
            for n in range(len(graph)):
                visits.add(n)
                dfs(n, 1, 0)
                visits.remove(n)
            return self.best

     


    Viewing all articles
    Browse latest Browse all 559

    Trending Articles