输入:有N个节点的无向图,每个节点被标注为0,1,…N-1。graph[i][j]表示从节点i到节点j有一条边。
输出:每个节点都访问一次,至少需要几步。
规则:可以重复访问一个节点。
分析:这道题目看了2个星期。其实这两周也是因为加班,没有再看新的题目。在地铁上没事,就把官方的解法方式拿出来看看。发现另有感悟。体会到了书读百遍其义自见。
 我们需要返回沿着边走完N个节点需要几步。因为我们可以从任意一个节点开始走。所以我们可以先问从节点0开始,走几步能访问了所有的节点。如果我们知道这个答案,那么我们分别计算从0,1,2…N-1开始,需要几步。取最小值就是答案。
 输入示例:[[1,2,3],[0],[0],[0]]
 先计算从一个节点开始。假设从节点0开始。可能的路径:节点0->节点1->?,之后需要再经过节点0,才有出路。我认为这道题目难的地方在于,之前为了防止重复访问,一个元素被访问之后做个标记,就可以。但是这里不可以。节点0->节点1->节点0->?如果此时再访问节点1,那就进入死循环了。既要一个节点访问多次,又要防止进入死循环。那么这里去重的不是节点,而是访问过的节点路径。
 状态1:节点0->节点1,访问了节点0和1,当前节点是1。
 状态2:节点0->节点1->节点0,也是访问了节点0和1,当前节点是0。
 上面的两种状态,虽然都只有两个节点被访问,但是当前节点不同,那么能选择的路径就可以不同。所以状态1和状态2是不同的状态,不能被放弃。
 状态3:节点0->节点1->节点0->节点1,也是访问了节点0和1,当前节点是1。描述完之后就发现状态3和状态1是一样的。而状态3的步数更多。所以状态3是属于重复状态,需要放弃。
 之后的可能的状态是:
 状态4:节点0->节点1->节点0->节点2
 状态5:节点0->节点1->节点0->节点2->节点0
 状态6:节点0->节点1->节点0->节点2->节点0->节点3
 也就是说需要5步可以遍历完所有节点。
 我们可以使用DFS或者BFS遍历边。编码的重点是解决怎么记录状态。我们需要记录当前已经访问了哪些节点,当前节点是哪个。前者使用bit数组记录。1=访问了节点0;3=访问了节点0和1;2=访问了节点1… 2N−1=2^N-1=2N−1=访问了所有节点。

节点标签 N-1 N-2 3 2 1 0
代表值 2N−12^{N-1}2N−1 2N−22^{N-2}2N−2 232^323 222^222 212^121 202^020
public class ShortestPathVisitingAllNodesV2 {public static void main(String[] args){int[][] graph = new int[4][];graph[0] = new int[]{1,2,3};graph[1] = new int[]{0};graph[2] = new int[]{0};graph[3] = new int[]{0};int r = new ShortestPathVisitingAllNodesV2().shortestPathLengthDFS(graph);System.out.println(r);}public int shortestPathLengthBFS(int[][] graph) {int N = graph.length;Queue<State> queue = new LinkedList();int[][] dist = new int[1<<N][N];for (int[] row: dist) Arrays.fill(row, N*N);int startNode = 1;dist[1<<startNode][startNode] = 0;queue.offer(new State(1<<startNode,startNode));//BFS遍历while(!queue.isEmpty()){int size = queue.size();for(int i=0;i<size;i++){State node = queue.poll();int d = dist[node.cover][node.head];if(node.cover == (1<<N)-1) return d;for(int child : graph[node.head]){int newCover = node.cover | 1 << child;if(dist[newCover][child]>d+1){dist[newCover][child] =  d +1;queue.offer(new State(newCover,child));}}}}throw null;}private int minDis = Integer.MAX_VALUE;public int shortestPathLengthDFS(int[][] graph) {int N = graph.length;int[][] dist = new int[1<<N][N];for (int[] row: dist) Arrays.fill(row, N*N);int startNode = 0;dist[1<<startNode][startNode] = 0;dfs(new State(1<<startNode,startNode),graph,N,dist);return minDis;}private void dfs(State state,int[][] graph,int N,int[][] dist) {if(state.cover == (1<<N)-1){minDis = Math.min(minDis,dist[state.cover][state.head]);}else{for(int child : graph[state.head]){int newCover = state.cover | 1 << child;if(dist[newCover][child]>dist[state.cover][state.head]+1){dist[newCover][child] = dist[state.cover][state.head]+1;dfs(new State(newCover,child),graph,N,dist);}}}}class State {int cover, head;State(int c, int h) {cover = c;head = h;}}
}

再进一步计算从各个节点开始。修改代码

     int startNode = 1;dist[1<<startNode][startNode] = 0;queue.offer(new State(1<<startNode,startNode));

修改为:

for(int startNode=0;startNode<N;startNode++){dist[1<<startNode][startNode] = 0;queue.offer(new State(1<<startNode,startNode));}

代码

847. Shortest Path Visiting All Nodes(二)相关推荐

  1. 847. Shortest Path Visiting All Nodes(三)

    DP 这道题目还可以用动态规划解决.在图论中解决最短路径问题有Dijkstra算法和bellman-ford算法.这道题目也需要用到DP.所以先学习一下这两个算法的思想和区别. 两个算法比较 Dijs ...

  2. ★☆★ lc 847. Shortest Path Visiting All Nodes

    https://leetcode.com/problems/shortest-path-visiting-all-nodes/description/ 一笔画问题,一笔画完一个图中的所有点,求最短路径 ...

  3. 847. Shortest Path Visiting All Nodes(一)

    输入:一个无向图,各个节点的标签是0.1.2-N-1.graph[i][j]表示从节点i到节点j有一条边. 输出:返回每个节点都访问一遍需要的最少步骤. 规则:各个节点可以重复访问. 分析: 如果可以 ...

  4. 程序员的算法课(19)-常用的图算法:最短路径(Shortest Path)

    一.最短路径问题 [google笔试题]一个环形公路,给出相邻两点的距离(一个数组),求任意两点的最短距离,要求空间复杂度不超过O(N). 如果从有向图中某一顶点(称为源点)到达另一顶点(称为终点)的 ...

  5. Shortest Path(翻译)

    http://noi.openjudge.cn/english/07/ There is a graph with N nodes. Given the length of each edge bet ...

  6. P - The Shortest Path in Nya Graph HDU - 4725

    P - The Shortest Path in Nya Graph HDU - 4725 最短路 不是 每两个点之间按层数设置边权 + 额外边权 TLE 是 相邻两层之间设置边权 + 额外边权 需注 ...

  7. [CF843D]Dynamic Shortest Path

    [CF843D]Dynamic Shortest Path 题目大意: 给定一个带权有向图,包含\(n(n\le10^5)\)个点和\(m(m\le10^5)\)条边.共\(q(q\le2000)\) ...

  8. zoj 2760 How Many Shortest Path 最大流

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 Given a weighted directed graph ...

  9. OSPF(Open Shortest Path First开放式最短路径优先)

    **协议** OSPF(Open Shortest Path First开放式最短路径优先)是一个内部网关协议(Interior Gateway Protocol,简称IGP),用于在单一自治系统(a ...

最新文章

  1. [转]slf4j + log4j原理实现及源码分析
  2. Linux下SVN服务器支持Apache的http和svnserve独立服务器
  3. 接口自动化实现图片上传(selenium/RF)
  4. 5.由键盘任意输入1个整形数据(小于10亿,位数不限),将其倒置,如:输入12345,则输出54321。
  5. Objective c类的初始化
  6. mysql项目数据库文档_项目mysql数据库
  7. 零基础iOS之Json及XML数据解析2
  8. [BZOJ1998][Hnoi2010]Fsk物品调度
  9. 正则表达式就这么简单!
  10. WebStorm配置Sass
  11. 【sketchup 2021】草图大师的高级工具使用3【复杂贴图制作实例(山体和球面贴图、全景天空绘制、吊顶添加光带)、图层(标记)工具使用、视图与样式工具的常规使用与高级使用说明】
  12. 求各位大神帮忙看一下我用51做的万年历程序有没有问题
  13. 基于Opencv的人脸&姓名&表情&年龄&种族&性别识别系统(源码&教程)
  14. 关于log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFa
  15. 【Python】matplotlib画图设置标题、轴标签、刻度、刻度标签(系列1)
  16. Java 媒体框架 之 JMF
  17. 基于树莓派的遥控小车
  18. 查找字符串fing()函数
  19. java马士兵网络编程_学习笔记-马士兵java - 网络编程
  20. Oxygen Eclipse 添加server

热门文章

  1. webpack-dev-server 搭建本地服务以及浏览器实时刷新
  2. React Native 一些事
  3. Android 颜色渲染(九) PorterDuff及Xfermode详解
  4. Windows Phone 7 开发积累_04
  5. 回顾2009,展望2010
  6. python 比赛成绩预测_大数据新研究:用六个月的跑步记录准确预测马拉松完赛成绩...
  7. linux进行monkey压力测试,App Monkey压力测试(一)
  8. 关于码云开源项目SpringBootAdmin多数据源配置
  9. 获取所有某格式文件到文件
  10. sql服务器如何复制数据库文件,如何将架构和一些数据从SQL Server复制到另一个实例?...