最短路径问题的延伸

3 篇文章 0 订阅

遇到一道与最短路径相关的问题,题目如下:

 

如图:

 

各边权值已经给出在对应边上。假设邮递员只能按照有边的路线走,以起点为1,必须经过的点为3,5,最后返回到起点1的路径中,给出一个有效算法寻找一条最小权路径(路径中每条边权之和最小)!
注意:允许在某边上来回,或者经过某些点多次,或者某些点没有经过,但必须经过顶点3,5至少一次。

现在我们来分析:

 

从1出发,经过3、 5,回到1,要使路径最短,其实就是要决定先到3还是先到5。

 

首先,可以把这个图存储为邻接矩阵MatrixG[6][6],求任意两点之间的最短路径Distance[6][6]有很多方法,比如Dijkstra,Floyd_Warshall,就不多说了。

 

那么这道题的解就是:

MIN( Distance[1][3]+Distance[3][5]+Distance[5][1], Distance[1][5]+Distance[5][3]+Distance[3][1])。

 

而且,由于该图为无向图,所以有Distance[1][3]+Distance[3][5]+Distance[5][1] ==  Distance[1][5]+Distance[5][3]+Distance[3][1]。

 

那么这道题的答案就直接出来了。

 

但是,如果把题目扩展一下:

给定一个图,节点个数为VerticesNum;

已知的邻接矩阵MatrixG[VerticesNum][VerticesNum];

给定出发点Stard,目的地Destination;

给定若干个必须经过的节点(运行时输入);

怎样给出最佳的路径呢?

 

首先,可以根据Dijkstra或者Floyd Warshall算法得出最短路径矩阵Distance[VerticesNum][VerticesNum]。

然后,求解此问题,需要构架出一个搜索树,这颗搜索树试探了所有的走法。

假设出发点为a,必须经过i、j、k三个节点,终点为b。

那么求解次问题,需要试探A(3,3)种走法(A(3,3)为3取3的排列),即:

a i j k b ;

a i k j b ;

a j i k b ;

a j k i b ;

a k i j b ;

a k j i b ;

 

看那一种走法路程最短。

 

如何构建这颗搜索树呢?

 

可以用递归:将需要经过的节点组成一个链表PassingNodes,构建一个这样的函数route(Stard,Destination,PassingNodes)。

 

route函数的实现:

 

如果PassingNodes为空,那么直接返回Distance[Stard][Destination]。

如果PassingNodes非空,那么:

MiniWeight = INT_MAX;

for each i in PassingNodes:

   remove node i form tPassingNodes;

   Weight = Distance[Stard][i] + route(i,Destination,PassingNodes);

   restore node i to PassingNodes;

   if (MiniWeight > Weight)
   {
    MiniWeight = Weight;
    RecordI = i;//记下路径

   }

 

path.push(RecordI);//记下路径。

return MiniWeight;

 

 

这样的递归所形成的搜索树,正是对PassingNodes(假如PassingNodes中节点个数为n)中所有节点的所有排列的尝试,即n取n的排列。

 

程序的核心就可以这样实现了,至于优化,以后有空再考虑。

 

我写出了程序的具体实现,但分了好几个模块,就不贴出来了。

可以参考一些我的另一篇博客:

http://blog.csdn.net/wtewrw/archive/2010/05/06/5564454.aspx

不是同一个问题,但是做法有点类似。

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值