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

来源:互联网 发布:淘宝客服部门奖罚制度 编辑:程序博客网 时间:2024/05/21 19:49

在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.


0 0