[LeetCode][H0847]访问所有节点的最短路径(java)(BFS+位运算)(状压DP)

847. 访问所有节点的最短路径

题目描述

给出 graph 为有 N 个节点(编号为 0, 1, 2, ..., N-1)的无向连通图。 

graph.length = N,且只有节点 i 和 j 连通时,j != i 在列表 graph[i] 中恰好出现一次。

返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。

 

示例 1:

输入:[[1,2,3],[0],[0],[0]]
输出:4
解释:一个可能的路径为 [1,0,2,0,3]

示例 2:

输入:[[1],[0,2,4],[1,3,4],[2],[1,2]]
输出:4
解释:一个可能的路径为 [0,1,4,2,3]

 

提示:

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

反思错误:

  1. 第一遍用的dfs,每个点进行dfs,超过2*n就停止,或者全部点都被访问截止,,,毫无疑问最后一个超时
  2. 之前没接触过状压DP,没想过用二进制位运算来代替状态,,厉害啊

解题思路:

在了解状压DP之前,首先要了解二进制位运算一些知识【这里有详细的状压DP及位运算;(我写的不会那么详细)】,

&  与运算:6(110)& 4(100) = 4(100),,,不解释了

|   或运算:6(110) |  4(100) = 6(110)

^  异或运算:6(110) ^  4(100) = 2(010)

<< 左移运算:1<<3 = 1 * 2³ = 8(1000)   将1(0001)向左移动3位 ==》  8(1000) ;简单理解就是左值乘以2的右值次幂。

>> 右移运算:相对应的就是向右移,,也就是除2

 

看这道题,拿示例一来说:

                        [LeetCode][H0847]访问所有节点的最短路径(java)(BFS+位运算)(状压DP)_第1张图片

图是这个样子的,,,我们首先要确定,每个点是否被访问过应该用二进制来表示,也就是

1(0001)代表0节点被访问,1、2、3没被访问。。

6(0110)代表1、2节点被访问,0、3没有………………{因为二进制数字0110从右往左数第零三位置为0,一二位置为1}

知道了每个节点的状态之后,创建dp[节点个数][所有状态都没被访问+1],,按这题来说

int[][] dp = new int[4][16]    ------------------因为我们最大状态(1111),申请的空间都是从零开始的,你不会不知道吧。我们需要申请大小为16(10000),所以是(10000),我也说不清了,,,,就类似我们数字有0、1、2、3,但是申请需要 [4] 。

然后需要两个Queue队列存储每个节点编号 id 和它对应的状态 state 

把初始每个点放入队列,让队列中每次都走一步,这样第一个出现走完所有点,也就是状态为(1111)的dp值就是最小路。

 

我觉得看代码更清晰。

Java代码:

class Solution {
    public int shortestPathLength(int[][] graph) {
        int n = graph.length;//number of points in graph
        int statelen = 1< queueid = new LinkedList<>();
        Queue queuestate = new LinkedList<>();
        //初始化
        int end=0;
        for(int i=0;i

 

你可能感兴趣的:(BFS,状压DP,LeetCode)