【问题标题】:Dijkstra's algorithm with 'must-pass' nodes具有“必须通过”节点的 Dijkstra 算法
【发布时间】:2014-08-18 17:19:44
【问题描述】:

我正在尝试实现 Dijkstra 算法,该算法可以找到起始节点和结束节点之间的最短路径。在到达末端节点之前,有一些“必须通过”的中间节点(超过一个),例如 2 或 3 个必须经过的节点,这些节点在到达末端节点之前必须经过。

如果我有一个必须通过节点,我找到的解决方案是找到两条不同的路径,从必须通过节点到目的地,从必须通过节点到起始节点。

我不知道如何实现这样的算法。 有什么建议吗?

谢谢。

List<Node> closestPathFromOrigin = null;

double maxD = Double.POSITIVE_INFINITY;
double _distance = 0;
int temp1 = 0;
List<Node> referencePath = new ArrayList<>();
boolean check = false;
Node startNode = null;

public List<Node> recursion(ArrayList<Node> points, ArrayList<Node> intermediatePoints) {

    if (!check) {
        System.out.println("--- DATA ---");
        System.out.println("Intermediate points: " + intermediatePoints);
        System.out.println("points: " + points.get(0).lat + " " + points.get(1).lat);
        System.out.println("--Find the nearest intermediate point from the start point of driver--");
        startNode = points.get(0);
        System.out.println("Start point of driver: " + startNode.lat + " " + startNode.lon);
        for (int i = 0; i < intermediatePoints.size(); i++) {
            List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
            _distance = 0;
            for (int j = 0; j < _path.size() - 1; j++) {
                _distance += calculateDistance(_path.get(j), _path.get(j + 1));
            }
            if (_distance < maxD) {
                maxD = _distance;
                closestPathFromOrigin = _path;
                temp1 = i;
            }
        }
        System.out.println("NearestPoint from driver's origin: " + intermediatePoints.get(temp1));

        referencePath.addAll(closestPathFromOrigin);
        startNode = intermediatePoints.get(temp1);
        System.out.println("New StartNode: the nearestPoint from driver's origin: " + startNode.lat + " " + startNode.lon);
        check = true;
        intermediatePoints.remove(intermediatePoints.get(temp1));
        System.out.println("New Intermediate points: " + intermediatePoints);
        System.out.println("Intermediate points empty? No -> recursion, Yes -> stop");
        if (!intermediatePoints.isEmpty()) {
            System.out.println("Recursion!!! with new data of: intermediatePoints: " + intermediatePoints);
            recursion(points, intermediatePoints);
        } else {
            System.out.println("Stop");
            return referencePath;
        }
    } else {
        System.out.println("Recursion: startNode: " + startNode.lat + " " + startNode.lon);
        for (int i = 0; i < intermediatePoints.size(); i++) {
            if (intermediatePoints.size() > 1) {
                System.out.println("From the new start point to the next nearest intermediate points if more than one points");
                List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
                _distance = 0;
                for (int j = 0; j < _path.size() - 1; j++) {
                    _distance += calculateDistance(_path.get(j), _path.get(j + 1));
                }
                if (_distance < maxD) {
                    maxD = _distance;
                    closestPathFromOrigin = _path;
                    temp1 = i;
                }
                referencePath.addAll(closestPathFromOrigin);
                startNode = intermediatePoints.get(temp1);
                check = true;
                intermediatePoints.remove(intermediatePoints.get(temp1));
                if (!intermediatePoints.isEmpty()) {
                    recursion(points, intermediatePoints);
                } else {
                    return referencePath;
                }
            } else {
                System.out.println("From the new start point to the next nearest intermediate points if just one point");
                List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
                //Collections.reverse(_path);
                referencePath.addAll(_path);
            }
            if (i == intermediatePoints.size() - 1) {
                System.out.println("Last Entry in intermediate points - find path to destination: " + points.get(1).lat + " " + intermediatePoints.get(i));
                //List<Node> _path1 = dijkstra(points.get(1), intermediatePoints.get(i));
                List<Node> _path1 = dijkstra(intermediatePoints.get(i), points.get(1));

                Collections.reverse(_path1);
                referencePath.addAll(_path1);
               //  referencePath.addAll(_path2);
            }
        }
    }
    return referencePath;
}

【问题讨论】:

  • 如果您必须通过节点,那么您将多次运行 Djikstra 算法。从开始到中间 1 执行相同的逻辑,然后再从中间 1 到中间 2,等等......直到你到达终点。
  • 告诉我们,你尝试了什么
  • 我尝试通过多次调用 Dijkstra 算法来做递归方法。首先找到距离起始节点最近的点。我只是添加上面的代码。
  • 是有向图。
  • @DanK 他没有指定必须通过的节点有顺序。你认为他如何有效地找到最优订单?

标签: java algorithm dijkstra depth-first-search


【解决方案1】:

这是旅行商问题的一般化。 TSP 出现在所有顶点都是“必须通过”的情况下。

找到每对必须通过的顶点之间的最短路径,从源到每个必须通过的顶点,以及从每个必须通过的顶点到汇点。然后使用著名的 TSP 的 O(n 2^n) 动态规划算法来找到满足您的约束的从源到接收器的最短路径;这里 n 将是 2 加上必须通过的顶点数。

【讨论】:

  • 非常感谢。您是否有教程链接以了解我如何实现 TSP 算法?
【解决方案2】:

通过查找必须包含节点和两个(结束和开始)节点之间的最短路径。形成图,然后运行最短路径算法(Dijkstra 算法)。开始和结束节点将相同。

【讨论】:

    【解决方案3】:

    不幸的是,这个问题被简化为 TSP,所以不要指望多项式解决方案,但如果没有中间节点很小,那么你可以相当快地做到这一点,如下所示:-

    1. 尝试所有可能访问的节点序列。
    2. 说你有s->a->b->c->d
    3. 然后使用 dijkstra 计算 min(s,d) + min(d,a) + min(c,d)
    4. 距离最短的序列就是您的答案。

    时间复杂度: O(k!*ElogV) 其中 k 不是必须通过的节点

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-03
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2013-11-26
      相关资源
      最近更新 更多