全路径搜索策略

1 为了能重用已有DijkstraSearcher的一些函数,添加一个类DirectedGraph继承自IGraph,重写虚函数。DirectedGraph中有Node类和Edge类。Node类需要std::vector<unsigned>aedge_ids字段,Edge类需要unsigned   snode_id;

       unsigned   enode_id;

       unsigned   direction : 2;

       unsigned   weight : 30;

2 传统Dijkstra在reach一个点时,如果该点是第一次遇到,则将其加入open队列,如果不是第一次遇到,则看是否能更新最短路径。

修改后的Dijkstra在reach一个点时,如果是第一次遇到,也是将其加入open队列:

如果不是第一次遇到,也跟第一次遇到一样,new一个ReachedNode,将其加入open队列。

传统Dijkstra代码里用一个hash_map<unsigned, ReachedNode*> ReachedNodes来存储所有reached的点,是为了能快速的通过nodeid得到reachednode结构,作用有两点:(1)能知道该nodeid现在的路径是多少,便于在第二次reach该点时判断是否需要更新路径长度(2)程序结束时能回溯出最短路径。

全路径搜索里,对每个node会有多个reachednode,它们里面存储的路径长度,parent信息不同,因此需要一个hash_map<unsigned, std::vector> ReachedNodes 来存储。

 

3为了控制搜索范围,用一个计数器conter来限制每个node被settle的次数。用一个hashmap来存储每个点对应的settle次数,如果次数等于counter了,就不再展开该点。

这一点能有效的控制环路。

如果一条路径上有一个小环,比如经过点A之后饶了一个小圈又经过A然后再往终点走,那么这条路径是走的很慢的,而其它的路径走的比它快的可能早就已经到达终点了。这个counter控制了每个点的settle次数,也就是说终点达到settle次数之后就停止搜索了,有可能其它路径走到终点了,而这条路径还没走到到时候,终点的settle次数就达到counter了,就停止搜索了,那么这条环路就算不出来了。当然,如果其它的路都非常非常远,而这条路很近,绕几个环路了还比别人近,那也会搜出来。

去掉环路后处理思路。比如到达点A时,发现它的parent是B,如果它已经有是B的记录了,那么就只保留一个就好了。这样就不会多次从B到A。

这样是不可行的! 这样不仅去掉了环路,也去掉了可能需要保留的路径,比如E到F到B到A和G到H到B到A我们都需要的话,这样一弄就只有一条了。

 

4搜索停止条件

(1)  open队列为空

(2)      target点settle次数为counter


多方案求路

一种思路:CH碰撞得到的多方案

另一种思路:全搜索,对所有方案聚类,得出差异度稍大的多方案

如何聚类?

采用kmeans。 定义两条路径的距离:1-2*两条route重复边长/两条route长之和

怎么计算聚类中心呢?簇中心是使其它点到该点的方差和最小的点,由于这里距离都是正数,因此简化为距离之和最小。逐个点计算其它点到该点的距离,取和。找出和最小的那个点作为聚类中心。这里的点就是一条路径。



你可能感兴趣的:(图论算法)