【问题标题】:Dijkstra shortest path on multiple unweighted graphs?多个未加权图上的 Dijkstra 最短路径?
【发布时间】:2022-01-19 16:45:06
【问题描述】:

我正在试图弄清楚如何实现 djiktra 算法来找到 2 个未加权图之间的最短路径。我得到的建议是使用 2 个图,一个用于红色,一个用于蓝色。旅行的成本始终为 1,但要在蓝色时访问红色方块,您需要支付 2 来切换图形。

我主要是在寻找建议和参考有没有人做过类似的事情???

【问题讨论】:

  • 您应该添加一些代码,到目前为止您尝试了什么?
  • 您仍然可以将其建模为一张图。红红边的权重为 1,红蓝边的权重为 3(正常行程为 1,切换颜色为 2)
  • 这不是未加权图。成本是 1 或 2(或者是 1 还是 3,问题没有说清楚)。这应该是应用此成本值的标准 Dijkstra 算法。
  • _我得到的建议是使用 2 个图表 _ 我建议忽略这个建议。它应该被建模为一个加权图。

标签: c++ graph-algorithm dijkstra


【解决方案1】:

基于原始图创建一个新的加权图,其中蓝色 -> 红色路径花费 3 而不是 1,然后在其上运行 Dijkstra。

编辑:可能没有必要实际创建新图,您可以直接从原始图获取权重,但首先创建新图可能更容易理解。

顶角如下所示:

A ← 3 → B ← 1 → C ← 1 → D ...
↑       ↑       ↑
1       1       3  
↓       ↓       ↓
E ← 3 → F ← 3 → G...

【讨论】:

  • 问题是,如果我通过支付 2 将颜色变为蓝色,我不应该每次在蓝色瓷砖上行走时都必须继续支付 3
  • 是的,只调整改变颜色的边缘的成本
  • 所以我需要在每次颜色变化时不断更改图形权重?
  • 我为您的原始图表的左上角添加了一个示例,希望它更清晰
  • 好吧,你的意思是,只有红色和蓝色连接在一起,成本才应该是 3,否则就是 1
【解决方案2】:

要创建图形,请使用此伪代码在节点之间添加边

AddEdge( n1, n2 )
SET cost = 1
IF n1color != n2color
   SET cost = 3;
graph.AddEdge( n1, n2, cost );
RUN Dijsktra on graph

【讨论】:

    【解决方案3】:

    这只是标准的 Dijkstra。

    这不是未加权的图,您需要从一个顶点移动到另一个顶点。从一种颜色切换到另一种颜色只是一个额外的规则,需要额外的费用。

    您所需要的只是一个计算两个顶点之间成本的函数,该函数只需查看每个顶点的颜色并适当地增加成本。请参阅:int getCost(Graph const& graph, Point src, Point dst) 下方。

    除此之外,它是您应该应用的标准算法。


    // Not pure C++
    // But left enough work that you have to make an effort
    // to complete this.
    
    enum Color { Red, Blue};
    using Graph = std::vector_like<std::vector_like<Color>>;
    using Point = std::pair<int, int>;
    
    int getCost(Graph const& graph, Point src, Point dst)
    {
        // Assumes: src and dst are 1 point away from each other.
        //          This assumes that work is done via
        //          getListOfPointsReachable() which only gets nodes
        //          nodes that are adjecent.
        //          
        // Standard movement cost.
        int cost = 1;
    
        // Add a cost if switching between blue red.
        if (graph[src] !=  graph[dst]) {
            cost += 2;
        }
        return cost;
    }
    
    std::list<Point> getListOfPointsReachable(Graph const& graph, Point src)
    {
        // Get a list of points that can be accessed by src.
        // All points that are next to the current and return as a list.
        // Check if they are out of bounds.
    }
    
    void Dijkstra(Graph const& graph, Point start, Point end)
    {
        std::set<Point>  visited;
    
        // Boundary:  int   => Cost
        //            Point => Point cost applies to.
        // Using tuple as it already has the comparison operator defined.
        using Boundary = std::tuple<int, Point>;
        std:: priority_queue<Boundary>   boundary;
    
        // Set up the boundary list with a start.
        boundary.emplace(0, start);
    
        while (!boundary.empty())
        {
            Boundary next = boundry.top();
            boundary.pop();
    
            int      cost = std::get<0>(next);
            Point    nextP = std::get<1>(next);
    
            if (nextP == end)
            {
                throw std::runtime_error("Found route to end: Cheapest Route is: " + cost);
            }
            if (visited.find(nextP) != std::end(visited))
            {
                // we already did this node.
                continue;
            }
            visited.insert(nextP);
    
            std::list<Point> dests = getListOfPointsReachable(graph, nextP);
            for (auto const& dest: dests)
            {
                int extraCost = getCost(graph, nextP, dest);
                boundary.emplace(extraCost + cost, dest);
            }
        }
        throw std::runtime_error("No Route from Start to End");
     }
    

    【讨论】:

      猜你喜欢
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多