这是单路径状态机矩阵的简单情况。
很抱歉伪代码是 C# 风格的,但是用对象来表达这个想法更容易。
首先,构造一个收费公路矩阵。
在What are some strategies for testing large state machines?阅读我对什么是收费公路矩阵的描述(不要理会 FSM 的答案,只是对收费公路矩阵的解释)。
但是,您描述的限制使案例成为一个简单的单路径状态机。它是覆盖范围最广的最简单状态机。
对于 5 个机场的简单案例,
vert nodes=src/入口点,
水平节点=dst/出口点。
A1 A2 A3 A4 A5
A1 x
A2 x
A3 x
A4 x
A5 x
请注意,对于每一行以及每一列,不应有多个转换。
要获得机器的路径,您可以将矩阵排序为
A1 A2 A3 A4 A5
A2 x
A1 x
A3 x
A4 x
A5 x
或者排序成对角方阵——有序对的特征向量。
A1 A2 A3 A4 A5
A2 x
A5 x
A1 x
A3 x
A4 x
其中有序对是票的列表:
a2:a1、a5:a2、a1:a3、a3:a4、a4:a5。
或更正式的表示法,
<a2,a1>, <a5,a2>, <a1,a3>, <a3,a4>, <a4,a5>.
嗯 .. 有序对吧?在 Lisp 中闻到一丝递归的味道?
<a2,<a1,<a3,<a4,a5>>>>
本机有两种模式,
- 旅行计划 - 你不知道怎么做
那里有很多机场,而你
需要一个通用的旅行计划
机场数量不详
- 旅行重建 - 你拥有一切
过去旅行的收费公路车票
但他们都是一大堆
你的杂物箱/行李袋。
我假设您的问题是关于旅行重建的。所以,你从那一堆票中随机挑选一张一张。
我们假设票堆大小不定。
tak mnx cda
bom 0
daj 0
phi 0
其中 0 值表示未排序的票。让我们将无序票定义为其 dst 与另一个票的 src 不匹配的票。
下面的下一张票发现 mnx(dst) = kul(src) 匹配。
tak mnx cda kul
bom 0
daj 1
phi 0
mnx 0
在您选择下一张机票的任何时候,它都有可能连接两个连续的机场。如果发生这种情况,您可以从这两个节点中创建一个集群节点:
<bom,tak>, <daj,<mnx,kul>>
并且矩阵被缩减,
tak cda kul
bom 0
daj L1
phi 0
在哪里
L1 = <daj,<mnx,kul>>
这是主列表的子列表。
继续挑选下一张随机票。
tak cda kul svn xml phi
bom 0
daj L1
phi 0
olm 0
jdk 0
klm 0
将existent.dst 匹配到new.src
或existent.src 到new.dst:
tak cda kul svn xml
bom 0
daj L1
olm 0
jdk 0
klm L2
<bom,tak>, <daj,<mnx,kul>>, <<klm,phi>, cda>
上述拓扑练习仅用于视觉理解。以下是算法解决方案。
这个概念是将有序对聚集到子列表中,以减少我们将用来存放票证的哈希结构的负担。逐渐地,将会有越来越多的伪票(由合并的匹配票组成),每个伪票都包含越来越多的有序目的地子列表。最后,将在其子列表中保留一张包含完整行程矢量的伪票。
如您所见,也许最好使用 Lisp 来完成。
但是,作为链表和映射的练习......
创建以下结构:
class Ticket:MapEntry<src, Vector<dst> >{
src, dst
Vector<dst> dstVec; // sublist of mergers
//constructor
Ticket(src,dst){
this.src=src;
this.dst=dst;
this.dstVec.append(dst);
}
}
class TicketHash<x>{
x -> TicketMapEntry;
void add(Ticket t){
super.put(t.x, t);
}
}
这样有效,
TicketHash<src>{
src -> TicketMapEntry;
void add(Ticket t){
super.put(t.src, t);
}
}
TicketHash<dst>{
dst -> TicketMapEntry;
void add(Ticket t){
super.put(t.dst, t);
}
}
TicketHash<dst> mapbyDst = hash of map entries(dst->Ticket), key=dst
TicketHash<src> mapbySrc = hash of map entries(src->Ticket), key=src
当一张票从一堆中随机抽取时,
void pickTicket(Ticket t){
// does t.dst exist in mapbyDst?
// i.e. attempt to match src of next ticket to dst of an existent ticket.
Ticket zt = dstExists(t);
// check if the merged ticket also matches the other end.
if(zt!=null)
t = zt;
// attempt to match dst of next ticket to src of an existent ticket.
if (srcExists(t)!=null) return;
// otherwise if unmatched either way, add the new ticket
else {
// Add t.dst to list of existing dst
mapbyDst.add(t);
mapbySrc.add(t);
}
}
检查是否存在 dst:
Ticket dstExists(Ticket t){
// find existing ticket whose dst matches t.src
Ticket zt = mapbyDst.getEntry(t.src);
if (zt==null) return false; //no match
// an ordered pair is matched...
//Merge new ticket into existent ticket
//retain existent ticket and discard new ticket.
Ticket xt = mapbySrc.getEntry(t.src);
//append sublist of new ticket to sublist of existent ticket
xt.srcVec.join(t.srcVec); // join the two linked lists.
// remove the matched dst ticket from mapbyDst
mapbyDst.remove(zt);
// replace it with the merged ticket from mapbySrc
mapbyDst.add(zt);
return zt;
}
Ticket srcExists(Ticket t){
// find existing ticket whose dst matches t.src
Ticket zt = mapbySrc.getEntry(t.dst);
if (zt==null) return false; //no match
// an ordered pair is matched...
//Merge new ticket into existent ticket
//retain existent ticket and discard new ticket.
Ticket xt = mapbyDst.getEntry(t.dst);
//append sublist of new ticket to sublist of existent ticket
xt.srcVec.join(t.srcVec); // join the two linked lists.
// remove the matched dst ticket from mapbyDst
mapbySrc.remove(zt);
// replace it with the merged ticket from mapbySrc
mapbySrc.add(zt);
return zt;
}
检查存在的src:
Ticket srcExists(Ticket t){
// find existing ticket whose src matches t.dst
Ticket zt = mapbySrc.getEntry(t.dst);
if (zt == null) return null;
// if an ordered pair is matched
// remove the dst from mapbyDst
mapbySrc.remove(zt);
//Merge new ticket into existent ticket
//reinsert existent ticket and discard new ticket.
mapbySrc.getEntry(zt);
//append sublist of new ticket to sublist of existent ticket
zt.srcVec.append(t.srcVec);
return zt;
}
我感觉上面有很多错别字,但这个概念应该是正确的。发现任何错别字,请有人帮忙改正。