【发布时间】:2015-05-19 01:23:37
【问题描述】:
我不熟悉 boost 库并尝试学习。我已经使用 boost 图形库来调用 dijstra 的最短路径函数来在地图中查找到目的地的路径。顶点是交叉点,边是街道段。
我正在以最短时间找到最短路径。为此,我将边缘权重定义为时间,时间 = st 段长度 * 它的速度/限制。这确实给了我最短的路径(按时间)。 但是,我还要考虑一个回合,并在每个回合的总时间上增加 15 秒。我如何检测转弯是给定两个街段(边缘),如果第二个 st 名称不等于第一个 st 名称,则它是一个转弯。
基本上,我想动态分配权重(不仅仅是像我在这里所做的那样在开始时设置它们)。当程序在搜索过程中访问边缘时,我希望它在这个阶段检查父母(或这里的前辈)。我如何在可以做到这一点的参数中传递一个函数或某些东西?
vector<unsigned> OurGraph::find_awesome_path(unsigned start, unsigned finish)
{
// start and finish are intersection IDs,
// Get the corresponding Vertices in the graph.
Vertex start_node = vertex_map[start];
Vertex dest_node = vertex_map[finish];
std::vector<Vertex> predecessors(boost::num_vertices(my_graph)); // To store parents
std::vector<float> distances(boost::num_vertices(my_graph)); // To store dijkstra distances
IndexMap indexMap = boost::get(boost::vertex_index, my_graph);
PredecessorMap predecessorMap(&predecessors[0], indexMap);
DistanceMap distanceMap(&distances[0], indexMap);
boost::dijkstra_shortest_paths(my_graph, start_node, boost::distance_map(distanceMap).predecessor_map(predecessorMap));
vector<Edge> path;
path = get_edge_path(dest_node, predecessorMap); // Extracts edges from edge descriptors in predecessor map
// and piles them in a vector of Edge.
return segment_list_from_edges(path); // Convert edges to street segment IDs and return.
}
其中 my_graph 是一个类型 Graph 和 Graph , Vertex, Edge, IndexMap, PredecessorMap 和 DistanceMap 是类型定义如下:
typedef boost::property<boost::edge_weight_t, float> WeightProperty;
typedef boost::property<boost::vertex_name_t, unsigned> IntersectionProperty;
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS,
IntersectionProperty, WeightProperty > Graph;
typedef boost::graph_traits < Graph >::vertex_descriptor Vertex;
typedef boost::graph_traits < Graph >::edge_descriptor Edge;
typedef boost::property_map < Graph, boost::vertex_index_t >::type IndexMap;
typedef boost::iterator_property_map < Vertex*, IndexMap, Vertex, Vertex& > PredecessorMap;
typedef boost::iterator_property_map < float*, IndexMap, float, float& > DistanceMap;
【问题讨论】:
-
您可能无法直接使用 Dijkstra 的算法,因为它假定沿某些边缘行驶所产生的额外成本与您如何开始顶点。您可以通过在同一条街道上的每对非相邻顶点 u 和 v 之间添加额外的边,然后将 每条 边的成本增加 15 秒(新边将包括15s 只需花费一次)。最后,无论你得到什么解决方案,都需要 15 秒的时间。注意:如果所有 n 个顶点都属于同一条道路,这可能是 O(n^2) 个额外的边!
-
我不太明白这个建议。在我有限的理解中,我做了以下事情(每次分别):(1)向短路顶点添加额外的边,这将是一个转弯。 (2) 在同一条街道上的顶点上添加额外的边。 (3) 赋予不同的权重值而不是0.25 ....包括大小常数、当前或下一段的长度、当前或下一段的时间。 ....它们要么返回非法路径(包括这些额外的边缘),要么没有区别,要么返回更糟糕的路径。
-
(2) 最接近正确。对于任意一对顶点 u 和 v 在同一条道路上,但不是彼此相邻,您需要添加一条边:这条边的目的是让 Dijkstra 选择对应的一系列来自原始图的边,而只支付 25 秒的转弯成本一次。所以例如如果您在同一条道路上有 5 个顶点 a、b、c、d、e,您将添加边 ac、bd、ce、ad、be、ae,每个边的成本等于它们“跨越”的边的总和+25(例如,be 的成本为 cost(bc)+cost(cd)+cost(de)+25)。所有原始边缘的成本也增加了 25。
-
如果 Dijkstra 在其解决方案中包含这些额外边之一,这意味着它“跨越”的原始边的底层集合(例如,添加的边 be 跨越原始边 bc、cd 和 de ) 是最短路径的一部分。
-
在新版本的图中,每条边需要额外花费 25s。这个想法是原始图中的每个 turnless subpath 对应于新图中的一条边,额外的 25s 是该子路径开始时所需的转弯的费用。 (从最终解决方案中减去 25,因为您不需要在开始时转弯。)虽然可以在新图中创建类似 ac->ce 的路径,即使它不离开也会收取额外的 25s同样的道路,Dijkstra 永远不会这样做,因为我们确保已经有更便宜的单边路径 ae。