SSL 1279 八皇后问题 位运算

在一个8×8的棋盘上放置8个皇后,并使它们相互不能攻击,即同一列、同一个对角线、同一行不能多于一个以上的皇后。求出所有的放置方案并输出。

这题我用的是位运算而不是dfs。

    和普通算法一样,这是一个递归过程,程序一行一行地寻找可以放皇后的地方。过程带三个参数,rowldrd,分别表示在纵列和两个对角线方向的限制条件下这一行的哪些地方不能放。位于该行上的冲突位置就用rowldrd中的1来表示。把它们三个并起来,得到该行所有的禁位,取反后就得到所有可以放的位置(用pos来表示)。这里的代码第6行就相当于pos and (not pos + 1),其结果是取出最右边的那个1。这样,p就表示该行的某个可以放子的位置,把它从pos中移除并递归调用递归过程。注意递归调用时三个参数的变化,每个参数都加上了一个禁位,但两个对角线方向的禁位对下一行的影响需要平移一位。最后,如果递归到某个时候发现row=11111111了,说明八个皇后全放进去了,于是找到的解的个数加一。

代码:

var
  w,ans:longint;
  f:array[1..8] of longint;

procedure dfs(row,ld,rd,d:longint);
var
  p,x,y,i:longint;
begin
  if row=w then
  begin
    inc(ans);
    for i:=1 to 8 do
      write(f[i],' ');
    writeln;
    exit;
  end;
  p:=w xor (w and (row or ld or rd));
  while p>0 do
  begin
    x:=p and (-p);
    y:=x;
    f[d]:=0;
    while y>0 do
    begin
      inc(f[d]);
      y:=y shr 1;
    end;
    dfs(row+x,(ld+x) shl 1,(rd+x) shr 1,d+1);
    p:=p-x;
  end;
end;

begin
  w:=1 shl 8-1;
  dfs(0,0,0,1);
  writeln(ans);
end.


你可能感兴趣的:(SSL 1279 八皇后问题 位运算)