从8-Queens解决方案到Prolog中更通用的n-Queens解决方案

时间:2013-04-05 17:28:35

标签: prolog n-queens

我正在研究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]是问题的解决方案是正确的:

  1. 子列表其他人本身就是一个解决方案(其他人不包含攻击列表中其他女王的女王)

  2. Y属于1到8之间的整数值(因为我有8行)

  3. 列表中的第一位女王不会接触子列表中的其他女王其他

  4. 然后定义了 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]).
    

    我不知道如何扩展以前的解决方案以处理可变数量的皇后。

1 个答案:

答案 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.

(我应该画它说如果没关系......)