847. 访问所有节点的最短路径
给出 graph
为有 N 个节点(编号为 0, 1, 2, ..., N-1
)的无向连通图。
graph.length = N
,且只有节点 i
和 j
连通时,j != i
在列表 graph[i]
中恰好出现一次。
返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
输入:[[1,2,3],[0],[0],[0]]
输出:4
解释:一个可能的路径为 [1,0,2,0,3]
输入:[[1],[0,2,4],[1,3,4],[2],[1,2]]
输出:4
解释:一个可能的路径为 [0,1,4,2,3]
1 <= graph.length <= 12
0 <= graph[i].length < graph.length
在了解状压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
看这道题,拿示例一来说:
图是这个样子的,,,我们首先要确定,每个点是否被访问过应该用二进制来表示,也就是
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值就是最小路。
我觉得看代码更清晰。
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