【问题标题】:How to modify this Held-Karp algorithm to search for Hamiltonian path instead of cycle?如何修改此 Held-Karp 算法以搜索哈密顿路径而不是循环?
【发布时间】:2017-01-06 14:54:07
【问题描述】:

我在Wikipedia 之后在 Java 中实现了 Held-Karp,它为循环的总距离提供了正确的解决方案,但是我需要它来给我路径(它不会在开始的同一个顶点上结束) .如果我从循环中取出重量最大的边缘,我可以获得路径,但是有可能2个不同的循环具有相同的总距离,但最大重量不同,因此其中一个循环是错误的。

这是我的实现:

//recursion is called with tspSet = [0, {set of all other vertices}]

private static TSPSet recursion (TSPSet tspSet) {
    int end = tspSet.endVertex;
    HashSet<Integer> set = tspSet.verticesBefore;

    if (set.isEmpty()) {
        TSPSet ret = new TSPSet(end, new HashSet<>());
        ret.secondVertex = -1;
        ret.totalDistance = matrix[end][0];
        return ret;
    }

    int min = Integer.MAX_VALUE;
    int minVertex = -1;
    HashSet<Integer> copy;

    for (int current: set) {
        copy = new HashSet<>(set);
        copy.remove(current);

        TSPSet candidate = new TSPSet(current, copy);

        int distance = matrix[end][current] + recursion(candidate).totalDistance;

        if (distance < min) {
            min = distance;
            minVertex = current;
        }
    }

    tspSet.secondVertex = minVertex;
    tspSet.totalDistance = min;

    return tspSet;
}

class TSPSet {
    int endVertex;
    int secondVertex;
    int totalDistance;
    HashSet<Integer> verticesBefore;

    public TSPSet(int endVertex, HashSet<Integer> vertices) {
        this.endVertex = endVertex;
        this.secondVertex = -1;
        this.verticesBefore = vertices;
    }
}

【问题讨论】:

    标签: java algorithm traveling-salesman


    【解决方案1】:

    您可以稍微改变动态编程状态。

    让路径从节点S 开始。让f(subset, end) 成为经过subset 中所有顶点并以end 顶点结束的路径的最优成本(Send 必须始终在subset 中)。过渡只是通过使用end-&gt;V 边添加一个新顶点V 而不是subset

    如果您需要以T 结尾的路径,答案是f(all vertices, T)

    附注:您现在所做的不是动态编程。这是一个详尽的搜索,因为您不会记住子集的答案并最终检查所有可能性(这会导致O(N! * Poly(N)) 时间复杂度)。

    【讨论】:

    • 是的,这种方法似乎有效。为什么这不是动态编程呢?我需要改变什么才能使用动态编程来做到这一点?谢谢。
    • @leonz 你需要添加备忘录。也就是说,您可以创建一个映射(整数集,最后一个节点)-> 值,这样您就不会两次计算同一状态的值。在您的代码中,可以多次计算状态的值。这是正确的,但使用记忆化可能会更快。
    【解决方案2】:

    当前方法的问题

    考虑这个图表:

    访问所有顶点的最短路径(每个顶点一次)长度为3,但最短循环为1+100+200+300,即使去掉最大权重边也是301。

    也就是说,通过从最短循环中删除一条边来构造最短路径是不正确的。

    建议的方法

    将循环算法转换为路径算法的另一种方法是向图中添加一个新节点,该节点对所有其他节点具有零成本边。

    原图中的任意一条路径都对应这个图中的一个环(路径的起点和终点就是额外节点所连接的节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      相关资源
      最近更新 更多