[BZOJ1087][SCOI2005]互不侵犯King解题报告|状压DP

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

 

  好像若干月前非常Naive地去写过DFS...

  然后其实作为状压DP是一道非常好的题啦><

  感觉直接无脑搞时间是下不来的 做了好几道预处理

  使得最后DP的过程中没有任何一条转移是无用的

  

 1 program bzoj1087;
 2 var i,x,n,k,j,p,q,t1,t2:longint;
 3     ans:int64;
 4     a:array[-1..512]of longint;
 5     b:array[-1..9,-1..100]of longint;
 6     c:array[-1..512,-1..512]of longint;
 7     f:array[0..1,-1..512,-1..512]of int64;
 8 
 9 function check(x:longint):boolean;
10 var las:longint;
11 begin
12     las:=0;
13     while x<>0 do
14     begin
15         if (x and 1=1)and(las=1) then exit(false);
16         las:=x and 1;
17         x:=x >> 1;
18     end;
19     exit(true);
20 end;
21 
22 function count(x:longint):longint;
23 var tem:longint;
24 begin
25     tem:=0;
26     while x<>0 do
27     begin
28         inc(tem,x and 1);
29         x:=x >> 1;
30     end;
31     exit(tem);
32 end;
33 
34 function ok(x,y:longint):boolean;
35 var i:longint;
36     tmp:array[0..1,-1..10]of longint;
37 begin
38     for i:=8 downto 0 do tmp[0,i]:=x >> i and 1;
39     for i:=8 downto 0 do tmp[1,i]:=y >> i and 1;
40     for i:=0 to 8 do if (tmp[0,i]+tmp[1,i]=2)or(tmp[0,i]+tmp[1,i-1]=2)or(tmp[0,i]+tmp[1,i+1]=2) then exit(false);
41     exit(true);
42 end;
43 
44 begin
45     fillchar(b,sizeof(b),0);
46     fillchar(a,sizeof(a),0);
47     fillchar(c,sizeof(c),0);
48         readln(n,k);
49         for i:=0 to 1 << n-1 do if check(i) then
50     begin
51             x:=count(i);
52         inc(b[x,0]);b[x,b[x,0]]:=i;
53         inc(a[0]);a[a[0]]:=i;
54     end;
55     for i:=1 to a[0] do
56         for j:=1 to a[0] do if ok(a[i],a[j]) then begin inc(c[a[i],0]);c[a[i],c[a[i],0]]:=a[j];end;
57     fillchar(f,sizeof(f),0);
58     for i:=0 to k do
59         for j:=1 to b[i,0] do f[1,i,b[i,j]]:=1;
60     for i:=2 to n do
61     begin
62         f[0]:=f[1];
63         fillchar(f[1],sizeof(f[1]),0);
64         for j:=0 to k do
65             for p:=0 to (n+1) >> 1 do if p<=j then
66             begin
67                 q:=j-p;
68                 for t1:=1 to b[p,0] do
69                     for t2:=1 to c[b[p,t1],0] do inc(f[1,j,b[p,t1]],f[0,q,c[b[p,t1],t2]]);
70             end;
71     end;
72     ans:=0;
73     for i:=1 to a[0] do inc(ans,f[1,k,a[i]]);
74     writeln(ans);
75 end.

 

转载于:https://www.cnblogs.com/mjy0724/p/4480049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值