从一个来源到多个目的地的最短路线(“旅行推销员”的简单变化)

时间:2017-04-25 20:54:44

标签: java algorithm graph shortest-path traveling-salesman

我正在尝试为以下问题实施解决方案:

给定有向非循环图中的源顶点和目标顶点列表,计算以最佳方式访问所有顶点的路径列表(访问的最小数量的不同顶点),假设没有“旅行成本”返回源顶点或先前访问过的顶点。

必须按顺序给出生成的路径,例如每条路径的第一个顶点必须是源顶点或前一个路径中之前访问过的顶点。因此,如果之前没有访问任何内容,则路径可以从任何访问过的顶点重新启动,或者从源顶点重新启动。

(不是家庭作业,我只是写了问题定义以使问题更清楚。我试图解决的问题是动态连接数据库上的表,因为我知道表关系图,我将是将一个表连接到许多其他表。在我的实际问题的简化中,源是图的“根”。)

所以给出了这个图:

  source = 1
         /   \
        2     3
        |     |
dest1 = 4     /
         \   /
   dest2 = 5

所以孩子低于父母。给定来源1以及目标45的预期结果将是:

Path 1 = 1 -> 2 -> 4
Path 2 = 4 -> 5

请注意,在这种情况下,从源到每个目标获得单独最短路径的简单实现会导致非最佳解决方案:

Path 1 = 1 -> 2 -> 4
Path 2 = 1 -> 3 -> 5

对顶点3进行“额外”访问。

我设法解决了第一个要求,即计算最佳路径列表。 但是我无法保证为给定目的地的所有不同排列保证所需的结果顺序。

所以在某些情况下我会计算类似的东西:

Path 1 = 4 -> 5
Path 2 = 1 -> 2 -> 4

到目前为止,这是我的代码:

public class ShortestPath {

  public ShortestPath(Vertex source) {
    // build shortest path from source to all children
  }

  public boolean hasPathTo(Vertex dest) {
    // returns true if there's a path to dest, false otherwise
  }

  public int distTo(Vertex dest) {
    // returns the distance to dest, or Integer.MAX_VALUE if there's no path
    // to dest
  }

  public Deque<Vertex> to(Vertex dest) {
    // returns path to dest, including source as the first element in the
    // path, or throws IllegalArgumentException if there's no path to dest
  }

  public Collection<Deque<Vertex>> to(List<Vertex> destinations) {
    Map<Vertex, Deque<Vertex>> destToPath = new HashMap<>();
    for (Vertex dest : destinations) {
      Deque<Vertex> path = to(dest);
      for (Map.Entry<Vertex, Deque<Vertex>> entry : destToPath.entrySet()) {
        Vertex source2 = entry.getKey();
        Deque<Vertex> path2 = entry.getValue();
        if (source2.shortestPath().distTo(dest) < path.size() - 1) {
          // If there's a shorter path from source2 to dest
          path = source2.shortestPath().to(dest);
        } else if (dest.shortestPath().distTo(source2) < path2.size() - 1) {
          // If there's a shorter path from dest to source2
          entry.setValue(dest.shortestPath().to(source2));
        }
      }
      destToPath.put(dest, path);
    }
    return destToPath.values();
  }
}

我尝试按层次顺序排序目的地,但这并没有解决结果顺序。我还试图创建一个Comparator来对结果进行排序,但我无法找到适合它的算法。

另外,我尝试改进上面的代码,以便它使用单独的List结构并执行add(i, path)来添加List中特定索引的路径,但是对于我的测试中使用的一些输入,我也做错了。

是否已经编写了一个算法来解决这个特定的问题?如果没有,那么任何一种方法可以保证上面指定的结果顺序吗?

编辑:对结果进行排序并不是那么简单。对于更复杂的结果,如:

Path 1 = 1 -> 2 
Path 2 = 2 -> 4
Path 3 = 4 -> 5

Comparator如何计算int compare(Deque<Vertex> o1, Deque<Vertex> o2)上面的路径1和路径3?

0 个答案:

没有答案