我有一个没有权重的定向循环图。我想找到A和B之间的最短路线(即跳数最少的路线)。
这是我到目前为止的代码:
path(A,B) :- walk(A,B,[]).
walk(A,B,V) :- edge(A,X), not(member(X,V)), (B=X); walk(X,B,[A|V]).
edge(a, b).
edge(b, c).
edge(a, d).
edge(c, a).
此代码打印为true,一次为其找到的每个路径。我该如何打印路径?我需要做些什么才能找到跳数最少的路径?
答案 0 :(得分:4)
一旦达到终止条件,您需要将额外参数与V
中积累的内容统一起来:
path(A,B,P) :- walk(A,B,[],P).
walk(B,B,V,P) :- reverse(V,P).
walk(A,B,V,P) :- dif(A,B), edge(A,X), maplist(dif(X),V), walk(X,B,[A|V],P).
一旦A
和B
相同,就意味着我们不必再走图了。在这种情况下,我们将V
中累积的路径反转为P
,该路径从path/3
“返回”。
注意:将检查递归终止的代码作为单独的规则,而不是使用;
几乎总是更清楚。
要查找跳数最少的路径,您可以找到所需两个点的所有路径,然后选择最小的路径:
shortest_path(A,B,S) :-
findall(P, path(A,B,P), Ps),
maplist(prepend_length, Ps, Ls),
sort(Ls, [[_,S]|_]).
prepend_length(P, [L,P]) :-
length(P,L).
答案 1 :(得分:1)
要产生路径,您需要添加一个参数来跟踪它;例如:
path(A,B,P) :- walk(A,B,[],P).
walk(A,B,V,[A,B]) :- edge(A,X), not(member(X,V)), (B=X).
(我会将递归案例作为练习。)
要查找最短路径,您可以找到所有路径(findall
)&选出最短的。