bzoj 1087: [SCOI2005]互不侵犯King 状压dp

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

用f[i,j,k]表示第i行状态为j放了k个国王有多少种方案。先dfs出符合条件的每种方案,然后进行转移。两个状态兼容的条件为i*2、i、i/2 and j都=0(i,j是状态)。

代码:

var
  n,m,i,j,k,l,a1:longint;
  ans:int64;
  a,b:array[1..100] of longint;
  f:array[1..9,1..100,0..100] of int64;
  d:array[1..9] of longint;

procedure dfs(x:longint);
var
  i:longint;
begin
  if x>n then
  begin
    inc(a1);
    for i:=1 to n do
    begin
      a[a1]:=a[a1]+d[i]*(1 shl (i-1));
      b[a1]:=b[a1]+d[i];
    end;
    exit;
  end;
  dfs(x+1);
  d[x]:=1;
  dfs(x+2);
  d[x]:=0;
end;

begin
  readln(n,m);
  dfs(1);
  for i:=1 to a1 do
    f[1,i,b[i]]:=1;
  for i:=2 to n do
    for j:=1 to a1 do
      for k:=b[j] to m do
        for l:=1 to a1 do
          if ((a[j] shl 1) and a[l]=0)and((a[j] shr 1) and a[l]=0)and(a[j] and a[l]=0) then
            f[i,j,k]:=f[i,j,k]+f[i-1,l,k-b[j]];
  for i:=1 to a1 do
    ans:=ans+f[n,i,m];
  writeln(ans);
end.


你可能感兴趣的:(bzoj 1087: [SCOI2005]互不侵犯King 状压dp)