我有一个数据翻译问题,并希望有关如何破解它的指导:
我有一个项目的入站列表,表示在旅程中分配给段的火车车厢。每个项目都有一个索引,一个汽车参考,一个起源和一个目的地。 E.g。
Index Car Origin Destination
1 C1 L1 L2
2 C2 L1 L2
3 C3 L1 L2
4 C1 L2 L3
5 C2 L2 L3
6 C4 L2 L3
上面的示例显示了四辆车(C1,C2,C3,C4)。汽车C1-C2从L1行驶至L3。 C3从L1行进到L2。 C4从L2行进到L3。该指数维持每条“腿”内的汽车顺序,但它是相对的:对于第二条腿(L2-L3),使用的第一个指数是4.
我需要将其翻译成一个不同的模型,提供一个独特的汽车列表,同时保持列车内的汽车顺序。 E.g。
Index Car Origin Destination
1 C1 L1 L3
2 C2 L1 L3
3 C3 L1 L2
4 C4 L2 L3
第二种车型不允许在中途完全重新订购火车车厢。即我不能允许汽车A,B,C,D将订单改为A,C,B,D。我将不得不应用一些启发式来获得最终的汽车订单,而且它不会反映现实。我很高兴接受这个缺点。
此外,尽管目标模型索引指定了列车内的车辆订单,但无论我是从列车的前部还是后部索引都无关紧要。在旅行中早些时候使用较低的indeces进行汽车分配会很不错。
所以,对于解决方案:我认为我需要使用图表来进行翻译,但我不确定从哪里开始。我认为我应该将汽车塑造成一个顶点,并将两辆汽车在同一条腿上作为边缘耦合。但我不知道我从哪里去。
我非常感谢有关如何解决问题的任何指示:建模技巧,合并算法......
修改 另一个复杂因素:在某些方面,列车中的汽车顺序可能完全颠倒。这用于表示列车改变了方向。我不需要捕获这种反转,但我确实需要保留汽车的相互连接顺序。
答案 0 :(得分:1)
本质上,除了反转段的问题之外,这个问题简化为topological sort,其中存在许多简单有效的算法(参见维基百科链接的例子)。要构建图形,我们将汽车用作顶点,并在Ci
到Cj
时插入边缘,如果Ci
在某条腿中紧跟Cj
之前。 (这可以最大限度地减少边数,从而降低O(V+E)
拓扑排序的成本。)
但那不会与#34;逆转"腿;这些将导致拓扑排序失败。所以问题的另一部分是检测反向腿。在这里,我假设没有明确的反转腿列表;如果有,解决方案将是显而易见的。
我认为以下方法合理有效,但可能不是最佳选择。
如果他们共享至少两辆汽车并且两条腿的共享汽车的订单相同,那么我们说两条腿是向前兼容的。类似地,如果两条腿共用至少两辆汽车并且共用汽车的顺序与另一条汽车中的共享汽车的顺序完全相反,则它们是反向兼容。最后,如果两条腿最多共享一辆汽车,那么两条腿是双向兼容的。 (可能两条腿不适合这三个类别中的任何一个,在这种情况下它们是不兼容的,问题没有解决方案。)
很容易对两条腿之间的关系进行分类。使用正确的数据结构(例如哈希表),找到两条腿之间共享汽车的列表是O(min(m,n))
,其中m和n是腿的大小(汽车数量),检查共享汽车是否正确在两个列表中以相同或相反的顺序出现。因此,构建所有可能的腿对之间的整个关系应该是O(L·N)
,其中L
是腿的数量,N
是汽车的数量。 (我没有这个断言的证据,所以它可能是错的。但这似乎是合理的。)
通过兼容性图表,我们需要为每条腿指定方向。我们使用图表的遍历来执行此操作,使用以下递归过程:
# Direction is either Forward or Reverse. We assume a function reverse(D) which
# returns Reverse if D is Forward, and Forward if D is Reverse
setDirection(Leg, Direction):
+ If the Direction of Leg is Direction, return.
+ If the Direction of Leg is set and not the same as Direction, fail.
+ Otherwise:
+ Set the Direction of Leg to Direction.
+ For each L such that Leg is forward compatible with L:
+ Call SetDirection(L, Direction)
+ For each L such that Leg is reverse compatible with L:
+ Call SetDirection(L, reverse(Direction))
setAllDirections():
+ while some Leg L does not have its direction set:
+ SetDirection(L, Forward)
现在,我们可以改变标记为颠倒的腿中汽车的顺序,并应用拓扑排序。
请注意,上述程序可能会产生一系列不符合" reality"的腿方向,因为在最后一行设置新Leg的初始方向的决定是完全武断但我认为这是我们能做的最好的事情。