dfs(S, Visited, Path) :-
move(S, S2),
\+member(S2, Visited),
dfs(S2, [S2|Visited], Path).
您好,
上面的代码是Prolog中dfs的原型。但是,move
基于回溯,因此我失去了Visited
列表,所以无法确保只访问每个节点一次。
如何在不使用全局变量和类似方法的情况下解决这个问题- 我想使用纯逻辑解决方案。
dfs(S, Visited, Path) :-
move(S, S2),
\+member(S2, Visited),
dfs(S2, [S2|Visited], Path).
您好,
上面的代码是Prolog中dfs的原型。但是,move
基于回溯,因此我失去了Visited
列表,所以无法确保只访问每个节点一次。
如何在不使用全局变量和类似方法的情况下解决这个问题- 我想使用纯逻辑解决方案。
Move
来检查可能的邻居。这里的区别在于您首先循环遍历可能的候选者。通过始终将它们放在堆栈的前面,我们会迭代地首先进入深度,因为堆栈的顶部将首先被探索。findall
来查找可能的下一个候选者。
示例:
%% Dfs starting from a root
dfs(Root) :-
dfs([Root], []).
%% dfs(ToVisit, Visited)
%% Done, all visited
dfs([],_).
%% Skip elements that are already visited
dfs([H|T],Visited) :-
member(H,Visited),
dfs(T,Visited).
%% Add all neigbors of the head to the toVisit
dfs([H|T],Visited) :-
not(member(H,Visited)),
findall(Nb,move(H,Nb),Nbs),
append(Nbs,T, ToVisit),
dfs(ToVisit,[H|Visited]).
findall/3
还是not
都不符合这一要求。 - false
path/4
以了解避免循环的一般解决方案。 - false