算法作业第十一周(leetcode)——847. Shortest Path Visiting All Nodes

 为了做一道图论题,我专门搜索了graph关键字找到了这道题。其实一开始是想做785那道题的,结果那道题看不懂。。。。这题终于不是动态规划题了(虽然似乎可以用动态规划做)。下面给出题目地址:

https://leetcode.com/problems/shortest-path-visiting-all-nodes/

这道题的意思就是说给出一个无向连通图,找出可以遍历所有点的最短路径。可以从任意点出发,并且每个点,每条边都可以经过多次。

这道题明确了数据范围,点的个数是小于等于12的,对于这么少的数据量,我认为可以暴力dfs试一下。但是如果单纯的的dfs很容易就会陷入循环,但是每个点可以多次经过,所以不可能单纯的用记忆化数组保存。实际上,我这里用了一个数组,保存经过每个点时已经经过的点的个数。只要dfs下一次到达同一个点时,它保存的已经过的点的个数与当前经过的点的个数相同。我们就可以知道它做了无用功,就判定为循环。

实际上 ,我们要进行一定程度的剪枝,最容易想到的就是通过一个变量来保存当前最短路径的长度,一旦大于等于就退出递归。如果点的个数为s,这个变量的初始值可以设成(s-1)*(s-1),因为从一个点到另一个点最多只需要(s-1)步。但实际上,我将这个变量设为了2*(s-1)。因为我们可以把这个连通图简化为树,树的遍历可以不超过2*边的个数,即2*(s-1)。

然而如果使用上面方法,是一定会超时的:

class Solution {
public:
    int pass[15];
    int maxstep;
    vector> graph2;
    int shortestPathLength(vector>& graph) {
        int i, ans;
        graph2 = graph;
        maxstep = (graph.size()-1) * 2;
        ans = maxstep;
        for(i=0;i=maxstep)
            return maxstep;
        for(i=0;i

实际上,在《算法竞赛入门经典》中,有提到过一种叫IDA*的优化。这种优化在我这个算法的表现形式就是判断还未经过的点的个数是否大于最短步长减去当前步长。就是说,每到一个新的点至少要一步,如果剩下的步数小于新的点的个数,就一定走不完,所以就剪枝掉。

下面给出代码,其实就改了一行代码:

class Solution {
public:
    int pass[15];
    int maxstep;
    vector> graph2;
    int shortestPathLength(vector>& graph) {
        int i, ans;
        graph2 = graph;
        maxstep = (graph.size()-1) * 2;
        ans = maxstep;
        for(i=0;i=maxstep+cnt)
            return maxstep;
        for(i=0;i

写完后去看了别人的博客,有的用dp,有的用floyd算法计算每两点之间距离,有的直接bfs,似乎还没有像我这样用dfs暴力搜索的,说明剪枝还是很有效的算法。

下面给出运行结果:

算法作业第十一周(leetcode)——847. Shortest Path Visiting All Nodes_第1张图片

你可能感兴趣的:(算法)