我在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;
}
}
答案 0 :(得分:1)
您可以稍微改变动态编程状态。
让路径从节点S
开始。让f(subset, end)
成为通过subset
中所有顶点并以end
顶点结束的路径的最佳成本(S
和end
必须始终在subset
)。转换只是使用V
边缘添加新的顶点subset
而不是end->V
。
如果您需要结束T
的路径,则答案为f(all vertices, T)
。
旁注:你现在所做的不是动态编程。这是一个详尽的搜索,因为您没有记住子集的答案并最终检查所有可能性(这会导致O(N! * Poly(N))
时间复杂度)。
答案 1 :(得分:0)