查找从一个城市到另一个城市的路径,然后在没有重新访问城市的情况下进

时间:2012-10-26 16:38:40

标签: algorithm data-structures

我在usaco上的算法上发现了一个问题,我无法链接到真正的问题,因为它需要身份验证才能粘贴它。

  

您刚刚赢得了比赛,奖品是加拿大的免费假期。你必须乘飞机旅行,城市从东到西订购。此外,根据规则,您必须从更远的城市西部开始,向东行驶直到您到达最东边的城市,然后向西飞行直到您到达您的起始位置。此外,您可以多次访问任何城市(当然除了起始城市)。

     

根据城市的顺序,可以完成的航班(你只能在某些城市之间飞行,只是因为你可以从城市A飞到城市B并不意味着你可以飞向另一个方向),计算您可以访问的最大城市数量。

这是动态编程教程文本的一部分。在教程中也给出了解决方案的建议。

  

想象一下,有两个旅行者来自西部大部分城市。旅客轮流向东行驶,下一位旅行者往往是最西边的旅客,但旅客可能永远不会在同一个城市,除非它是第一个或最后一个城市。但是,其中一位旅行者只允许进行“反向飞行”,只要有从B市到A市的航班,他就可以从A市到B市旅行。

     

通过将正常旅行者的路径带到最东部的城市,然后将另一个旅行者的路径反向回来,可以看出两个旅行者的路径可以组合起来进行往返旅行并不难。到了最西部的城市。此外,当旅行者x被移动时,你知道旅行者y还没有访问旅行者x以东的任何城市,除了城市旅行者y是当前的,否则旅行者y必须已移动一次,而x在y的西边。

据我了解解决方案,我认为解决方案可以通过保持向前方向的外向城市的一维表和反方向的外向城市表来完成。 例如。如果我有5个城市,A,B ...... E朝向所需的方向,城市之间的有向图是A是开始城市,E是目的地。

   A | B | C | D | E
A  0 | 1 | 0 | 0 | 0
B  0 | 0 | 1 | 1 | 0
C  1 | 0 | 0 | 0 | 1
D  0 | 0 | 0 | 0 | 1
E  0 | 0 | 1 | 0 | 0

我保留两个表一个用于传出城市我将通过将第一个城市初始化为1来填充它。访问的最大城市数量,然后每个下一个条目扫描当前城市存在路径的所有先前城市,然后选择最大值,对反向旅行者执行相同操作。

table[i] = Max(j=i to 0) (table[j])

我将在目的地城市拥有最大值,但这并不能保证任何城市都不会重复。如果我在数组字段中再保留一个条目以及最大数字,我将无法将其从正向切换为反向。我正在学习动态编程,所以可能是我没有得到正确的想法。 这是我为图表

构建的表格
A | B | C | D | E
1 | 2 | 3 | 3 | 4
1 | 1 | 2 | 1 | 3

因此两者都将获得最大值。请提供方向/提示,以便我可以朝着正确的方向前进。

PS。这不是一个家庭作业问题

1 个答案:

答案 0 :(得分:0)

您使用这两个表格的方法可以独立模拟每位旅行者的状态,因为已经访问过的城市数量,以及旅行者目前居住的位置。当你发现自己时,这不会阻止两次访问城市。

相反,我使用三个元素来模拟州:一个旅行者当前所在的城市,另一个旅行者所在的城市,以及他们总共访问过的城市数量,即他们的总和个人数量。所以你有一个2d表,而不是你的两个1d表。单元格( f r )将包含前方旅行者在城市 f 时访问的最多已知城市总数,而反向旅行者是在城市 r

您可能会按照其最小元素的顺序迭代这些状态。这意味着你接下来会扩展一个尚未扩展的状态,并且这两个数中较小的数字在所有未扩展状态中最小。如果处于该状态, f < r ,然后您可以使用 f'来更新状态( f' r > r ,如果有从 f f' 的航班。另一方面,如果 r < f 您使用 r' >更新( f r' f 以及从 r' r 的航班。

在伪代码中:

first = (f: 0, r: 0)  # tuple with two members, called f and r
todo = set { first }  # a set with a tuple as its only element
visited = a map from tuples to integers, unset values defaulting to 0
visited[first] = 1
while todo is not empty:
  best = ∞
  cur = null
  for t in todo:
    if min(t.f, t.r) < best:
      best = min(t.f, t.r)
      cur = t
  todo.remove(cur)
  if (cur.f < cur.r):
    for f' in cities where flights from f arrive:
      next = (f: f', r: cur.r)  # keep r but use f' as the new f
      todo.add(next)            # will do nothing if it already is in the set
      visited[next] = max(visited[next], visited[cur] + 1)
  else:
    for r' in cities where flights to r depart:
      next = (f: cur.f, r: r')
      todo.add(next)
      visited[next] = max(visited[next], visited[cur] + 1)
best = 0
for cur in keys of visited:
  if best < visited[cur]:
    if there is a flight from cur.f to cur.r: # can close the tour
      best = visited[cur]
return best
相关问题