SSL 1382 车 状压dp

在n*n(n≤20)的方格棋盘上放置n个车(可以攻击所在行、列),有些格子不能放,求使它们不能互相攻击的方案总数。 

我们用ar表示第r行不允许放置的情况,如果第r行某一位不允许放置则ar此位为0,否则为1,这可以在读入数据阶段完成。然后对于需要处理的状态s,用ts=s&ar来代替s进行枚举,即不枚举s中的1转而枚举ts中的1。因为ts保证了不允许放置的位为0,这样就可以不用其它的判断来实现算法
代码:

var
  n,i,t,s,ts,m,x,y:longint;
  f:array[0..2000000] of int64;
  a:array[1..20] of longint; 
begin
  readln(n);
  for i:=1 to n do
    a[i]:=1 shl n-1;
  readln(m);
  for i:=1 to m do
  begin
    readln(x,y);
    a[x]:=a[x] xor (1 shl (y-1));
  end;
  f[0]:=1;
  for i:=1 to 1 shl n-1 do
  begin
    t:=i;
    s:=0;
    while t>0 do
    begin
      inc(s);
      t:=t xor (t and -t);
    end;
    ts:=i and a[s];
    while ts>0 do
    begin
      f[i]:=f[i]+f[i xor (ts and -ts)];
      ts:=ts xor (ts and -ts);
    end;
  end;
  writeln(f[1 shl n-1]);
end.


你可能感兴趣的:(SSL 1382 车 状压dp)