我必须找到两个州之间的路线,我已到达这里,我现在有错误,关于堆栈帮助我
% state 1 is border of state 2
% borders(A , B).
borders(sasktchewan, alberta).
borders(saskatchewan, manitoba).
borders(saskatchewan, nwt).
borders(alberta, british_columbia).
borders(alberta, saskatchewan).
borders(alberta, nwt).
borders(british_coumbia, yukon).
borders(british_coumbia, nwt).
borders(british_coumbia, alberta).
borders(nwt, saskatchewan).
borders(nwt, alberta).
borders(nwt, british_columbia).
borders(nwt, yukon).
borders(nwt, manitoba).
borders(manitoba, saskatchewan).
borders(manitoba, nwt).
route( A, B, [ go(A,B) ] ) :- borders( A, B ).
route( A, B, [ go(A,Z) | ZtoB ] ) :- borders( A, Z ), route( Z, B, ZtoB ).
答案 0 :(得分:2)
问题在于你不会在你已经去过的地方保管。现在说你希望从sasktchewan
转到manitoba
。 Prolog将评估为:
(sasktchewan) <--------------
`--(alberta) \
`--(british_columbia) |
|--(yukon) fail! |
`--(nwt) |
`-(sasktchewan)---/
既然你不会告诉prolog你不能进入循环,它会继续追踪(sasktchewan) -> (alberta) -> (nwt)
到路径并且永远不会找到目标目标。
演示:
?- route(sasktchewan,manitoba,L).
L = [go(sasktchewan, alberta), go(alberta, saskatchewan), go(saskatchewan, manitoba)] ;
L = [go(sasktchewan, alberta), go(alberta, saskatchewan), go(saskatchewan, manitoba), go(manitoba, nwt), go(nwt, manitoba)] ;
L = [go(sasktchewan, alberta), go(alberta, saskatchewan), go(saskatchewan, nwt), go(nwt, manitoba)] ;
L = [go(sasktchewan, alberta), go(alberta, nwt), go(nwt, manitoba)] ;
L = [go(sasktchewan, alberta), go(alberta, nwt), go(nwt, saskatchewan), go(saskatchewan, manitoba)] ;
L = [go(sasktchewan, alberta), go(alberta, nwt), go(nwt, manitoba), go(manitoba, saskatchewan), go(saskatchewan, manitoba)] ;
您需要做的是使用累加器列出您已经去过的所有地方。从您已经访问过该城市的那一刻开始每次进行会员检查时,您就会中断。因此:
%We start a route with being in city A
route(A, B, L) :-
route(A, B,[A], L).
%In case we find a city with a border, don't hesitate and go to the city!
route( A, B,_,[go(A,B)]) :-
borders(A,B).
%Too bad, now looking for an extra city
route(A,B,Been,[go(A,Z)|ZtoB]) :-
borders(A,Z), %hahaa, we can access city Z
\+ member(Z,Been), %hold on! Did we already visit Z. No! we didn't
route(Z,B,[Z|Been],ZtoB). %Log city Z and look for a root from Z to B
这是不最佳:一旦访问城市 a 在一条路径上失败,如果你走另一条路径到那个城市,也会失败。您可以使用non-bactrackable商店维护您已访问过的城市列表,以便将其转换为 O(n 2 )算法。实施取决于方言。