【发布时间】:2012-09-15 11:47:42
【问题描述】:
我有一个类似于下面的无向图,我需要实现一个图遍历算法。
示例:
http://i.imgur.com/15L6m.png
这个想法是每个顶点都是一个城市,每个边都是一条道路。
边的权重表示遍历指定边所需的时间。
条件是:
- 每条边都在指定的时间窗口中打开以供遍历:Time Open1、Time Open2、TimeClose1、Time Close2 - 当前时间必须在这些时间间隔内才能遍历边。
- 只有一些顶点必须被访问。每个顶点必须在指定的时间窗口内至少访问一次:Time Open1、Time Open2、TimeClose1、Time Close2 - 当前时间必须在这些时间间隔内才能将顶点标记为已访问。
- 起点始终是顶点 0
对于我的例子,我有:
必须访问的顶点及其时间窗口(不考虑 -1 的值):
Vertex To1 Tc1 To2 Tc2
1 0 260 340 770
4 0 240 -1 -1
5 170 450 -1 -1
边在以下时间窗口中打开(不考虑带 -1 的值 考虑):
Edge To1 Tc1 To2 Tc2
0-1 0 770 -1 -1
0-4 0 210 230 770
0-5 0 260 -1 -1
1-2 0 160 230 770
1-5 40 770 -1 -1
2-4 80 500 -1 -1
3-4 60 770 -1 -1
3-5 0 770 -1 -1
所以基本思路是从顶点0开始,找到最短的路线遍历
考虑到指定时间的顶点 1、4 和 5。
此外,例如,如果您已完成 0-1 但不能使用 1-5,则可以执行 0-1-0-1-5。
我现在正在使用的一个可能的解决方案是:
从 0 开始。在最短的时间段内找到最近的顶点进行标记(我使用
修改的 Dijkstra 算法)。这样做直到我标记了所有需要的顶点。
问题是我认为我没有找到所有的可能性,因为正如我所说
你也可以像 0-1-0-1-5 组合一样四处走动,最后你可能会得到一条更短的路线。
为了更清楚,我必须找到最短路径,以便我从顶点 0 开始,以一个目标顶点结束,同时我已经访问了所有其他目标顶点至少一次,尊重施加在边缘上的条件和目标顶点。
例如:
一个可能的解决方案是 0 - 4 - 3 - 5 - 1,总时间为 60+50+60+50=220
从 0 我也可以直接转到 5 但如条件中所述以标记顶点 5
我必须有 170 到 450 之间的累积时间。另外,如果我去 0-4,我不能使用边缘 4-2,因为它在 80 处打开并且我的累积时间是 60。注意我可以使用 0-4-3,因为 4 -3 在 60 处打开,执行 0-4 所需的时间等于 60。
首先,我将使用最多 20 个顶点和 最多约 50 条边。
解决方案 1:
0
1 4 5
0 2 5 0 2 3 0 1 3
我所做的是通过访问每个相邻顶点构建类似于树的东西来遍历图形。我在以下情况下停止扩展分支:
1. 我有太多重复项,例如 0 1 0 4 0 1 0 - 所以我停下来,因为我有一组重复的 0 值,即 4
2. 我找到一条包含所有要标记的顶点的道路
3. 我发现一条路比另一条完整的路要花更长的时间
4. 我不能创建另一个节点,因为边缘是封闭的
解决方案 2:
应用@Boris Strandjev 示例,但我有一些问题:
我必须在其间隔内至少访问节点 1,4 和 5 一次,允许在间隔外访问但不标记。对于一个顶点,我有 {(, time)},其中 id1 是当前顶点的 ide,id2-4 表示 1,4,5 的布尔值,如果在指定的时间间隔内访问,时间 -路径中的当前时间
Step1:
{<0, 000>, 0} I can visit - {<1, 100>, 60} - chosen first lowest val
- {<4, 010>, 60}
- {<5, 000>, 60}
Step2:
{<1, 100>, 60} - {<0, 100>, 120}
- {<2, 100>, 110} - chosen
- {<5, 100>, 110}
Step3:
{<2, 100>, 110} - {<1, 100>, 160} - if I choose 1 again I will have a just go into a loop
- {<4, 110>, 170}
Step4:
{<4, 110>, 170} - {<0, 110>, 230}
- {<2, 110>, 230}
- {<3, 110>, 220} - chosen
Step5:
{<3, 110>, 220} - {<4, 110>, 270} - again possible loop
- {<5, 111>, 280}
Step6:
{<5, 111>, 280} - I stop Path: 0-1-2-4-3-5 cost 280
编辑:
我最终使用了上述两种解决方案的组合。一切似乎都很好。
【问题讨论】:
-
您是在寻找从顶点 0 到每个目标顶点的最短路径,还是从 0 开始并访问每个目标顶点的单个游览?后一个问题与旅行商问题有关,并且是 NP-hard。
-
除了进行那些“往返”(0-1-0-1-5)之外,是否也可以在某个节点上等待直到所需的边缘可用?在这种情况下,您可以搜索忽略时间限制的路径,然后进行一些“后处理”以将等待时间添加到路径。
-
不,您不能等待边或顶点可用,您必须在所有条件下找到最佳解决方案。只有当你穿过一条边时,时间才会前进。
-
@mUncescu:你所做的并不完全是 Dijkstra,它看起来更像是光束搜索。在 Dijkstra 中,增加路径的堆在每一步中都会扩展,但这并不意味着您丢弃旧的、未使用的路径。因此,第 3 步对您来说应该是
{<4, 010>, 60}或{<5, 000>, 60},因为它的时间比{<2, 100>, 110}的时间短。总体而言,在第 2 步之后,您有 5 条扩充路径可供选择:{<4, 010>, 60}, {<5, 000>, 60}, {<0, 100>, 120} , {<2, 100>, 110}, {<5, 100>, 110}。对不起,也许我的例子有点令人困惑......
标签: algorithm graph graph-traversal