我正在 Prolog 学习 SWI Prolog 实施的大学考试。
我对这个版本的 8 Queen 问题如何使用排列解决问题有一些疑问:
solution(Queens) :-
permutation([1,2,3,4,5,6,7,8], Queens),
safe(Queens).
permutation([],[]).
permutation([Head|Tail],PermList) :-
permutation(Tail,PermTail),
del(Head,PermList,PermTail).
del(Item,[Item|List],List).
del(Item,[First|List],[First|List1]) :-
del(Item,List,List1).
safe([]).
safe([Queen|Others]) :-
safe(Others),
noattack(Queen,Others,1).
noattack(_,[],_).
noattack(Y,[Y1|Ylist],Xdist) :-
Y1-Y=\=Xdist,
Y-Y1=\=Xdist,
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).
在以前的解决方案中,我使用了这个解决方案模板: [1\Y1, 2\Y2, 3\Y3, 4\Y4, 5\Y5, 6\Y6, 7\Y7, 8\Y8] 简单地说每个女王都有要在不同的行上,X 值可能会受到限制。
这个版本的程序有很大的不同,因为我们可以观察到,为了防止垂直攻击,所有的皇后都必须在不同的行上,所以我每行都有一个皇后。
因此,在不丢失信息的情况下,我可以说解决方案将是列表的排列:[1,2,3,4,5,6,7,8],其中每个元素都表示女王的 Y 坐标。
所以在这种情况下,我只通过它的 Y 坐标(它的行索引)来表示一个皇后位置
所以我有解决方案的关系,而不是说如果皇后是[1,2,3,4,5,6,7,8]原始列表的前排列并且如果这个排列是安全的(每个皇后在这个排列列表不攻击其他女王)。
好的,这很清楚......现在它定义了安全关系。
有一个基本情况说,如果列表为空,那么这是安全的,因为没有攻击。
并且有一个一般情况,列表不为空。如果列表不为空,我可以将其划分为[Queen|Others],其中Queen是列表中的第一个皇后, Others是剩余的子列表......所以如果子列表 Others 它,原始列表[Queen|Others]是安全的本身就是一个解决方案(如果是安全的,如果Others中没有攻击的话)并且如果第一项Queen没有攻击其他子列表中的另一个Queen...
好的......直到现在我认为这对我来说很清楚......
现在我对noattack关系的定义有一些问题!
问题是我只通过它的 Y 坐标和 X 坐标来表示一个皇后位置,它没有明确存在。
我知道为了规避这种表示的限制,有以下概括(我希望能很好地理解......我不太确定......):**我也知道每列必须有一个女王棋盘的,所以与列表中的第一个皇后(Queen)和子列表Others的X距离必须为1**
第一项Queen和子列表Others的距离是第一项Queen和最接近它的Queen的X距离,我的推理是否正确?
因此,如果女王在不同的列上,则noattack关系为 TRUE(对于构造总是正确的),我可以表示必须在不同的行上,说从女王和其他子列表中最近的女王的 X 距离为 1。
但是,如果我的推理是正确的,我会发现很多麻烦试图理解这部分代码中这个东西是多么的好:
noattack(Y,[Y1|Ylist],Xdist) :-
Y1-Y=\=Xdist,
Y-Y1=\=Xdist,
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).