我正在研究Prolog的普遍性,我对以下练习有一些问题。
我有以下8-Queens问题的经典解决方案(对我来说这不是问题),修改此解决方案我必须为处理可变数量的皇后的更通用的n-Queens问题创建一个新的解决方案
solution([]).
solution([X/Y|Others]) :- solution(Others),
member(Y,[1,2,3,4,5,6,7,8]),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
% Q e Q1 sono su diagonali diverse:
Y1-Y =\= X1-X,
Y1-Y =\= X-X1,
% Q non attacca regine nella sottolista Others:
noattack( X/Y, Others).
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
好的,这个程序看起来很简单:我有一个女王的名单,他们不能互相攻击。
如果女王的名单是空的,则女王不可能攻击列表中的另一个女王,所以空列表是问题的解决方案(这是解决方案的基本情况)
* 如果女王的名单不是空的,我可以把它分成[X / Y |其他],其中X / Y在列表中的第一个女王的板上有一个rappresent位置(位置是夫妻(X,Y)的rappresentend,其中X是列,Y是行)
因此,如果以下关系为真,那么列表[X / Y | Others]是问题的解决方案是正确的:
子列表其他人本身就是一个解决方案(其他人不包含攻击列表中其他女王的女王)
Y属于1到8之间的整数值(因为我有8行)
列表中的第一位女王不会接触子列表中的其他女王其他
然后定义了 noattack 关系,指定何时我可以说女王不会攻击另一个女王(这很简单:它们不能保持不变线,在同一列上,在同一对角线上)
最后我有一个解决方案模板,它简化了我的生命,限制X值的值从1到8(因为我知道2个皇后不能留在同一列...所以每个解决方案中的女王留在与其他所有女王不同的栏目上)
所以我认为在我指定列数的行上最大的问题是:
member(Y,[1,2,3,4,5,6,7,8])
并在我定义解决方案模板的行上:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
我不知道如何扩展以前的解决方案以处理可变数量的皇后。
答案 0 :(得分:2)
似乎很容易,传递大小:
solution(_, []).
solution(N, [X/Y|Others]) :-
solution(N, Others),
between(1, N, Y),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
Y1-Y =\= X1-X, % Q e Q1 sono su diagonali diverse
Y1-Y =\= X-X1,
noattack( X/Y, Others). % Q non attacca regine nella sottolista Others
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template(N, L) :-
findall(I/_, between(1,N,I), L).
试验:
?- N=6, template(N, L), solution(N, L).
N = 6,
L = [1/5, 2/3, 3/1, 4/6, 5/4, 6/2] ;
N = 6,
L = [1/4, 2/1, 3/5, 4/2, 5/6, 6/3] ;
N = 6,
L = [1/3, 2/6, 3/2, 4/5, 5/1, 6/4] ;
N = 6,
L = [1/2, 2/4, 3/6, 4/1, 5/3, 6/5] ;
false.
(我应该画它说如果没关系......)