BZOJ1087 互不侵犯 题解

【题目描述】

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

【样例输入】

3 2

【样例输出】

16

【解题思路】

本题为SCOI2005的题,正解应该是状态压缩动态规划,把所有方案变为二进制存储,1为该位置摆放了国王,0为没有,因为一行最多九个格子,也就是说最多为511,空间上完全可以接受。然后我们可以先预处理一下所有可行的国王摆放的位置,以减少动规的次数,设f[i,j,k]为现在是第i行,用第j种方案,一共摆放了k个国王的总方案数,那么我们动规的条件就是f[i,j,k]=∑f[i-1,s,t]{s为与j不冲突的方案,t<=k}

于是对于每个可行方案,我们需要记录一些东西:这个可行方案摆了多少国王,这个可行方案的攻击范围。那么满足条件的s即为s and j=0。

【代码实现】

 1 type rec=record
 2      j,l,p:longint;
 3 end;
 4 var f:array[1..9,0..512,0..80] of int64;
 5     n,m,i,j,w,k,q,total,l:longint;
 6     ans:int64;
 7     fl:boolean;
 8     fa:array[1..500] of rec;
 9 procedure dfs(w,dep,t:longint);
10 var i:longint;
11     s:string;
12     ch:string;
13 begin
14  if dep>n then
15   begin
16    inc(total);
17    fa[total].j:=t;
18    i:=t;
19    s:=‘‘;
20    while i<>0 do
21     begin
22      if i and 1=1 then
23       inc(fa[total].l);
24      str(i and 1,ch);
25      s:=ch+s;
26      i:=i shr 1;
27     end;
28    while length(s)<n do
29     s:=‘0‘+s;
30    for i:=n downto 1 do
31     if i=1 then
32      begin
33       if (s[i]=‘1‘)or(s[i+1]=‘1‘) then
34        fa[total].p:=fa[total].p+(1 shl (n-i));
35      end
36     else
37      if i=n then
38       begin
39        if (s[i]=‘1‘)or(s[i-1]=‘1‘) then
40         fa[total].p:=fa[total].p+1;
41       end
42      else
43       if (s[i]=‘1‘)or(s[i-1]=‘1‘)or(s[i+1]=‘1‘) then
44        fa[total].p:=fa[total].p+(1 shl (n-i));
45    exit;
46   end;
47  if w=1 then
48   dfs(0,dep+1,t)
49  else
50   for i:=0 to 1 do
51    begin
52     t:=t+i shl (dep-1);
53     dfs(i,dep+1,t);
54    end;
55 end;
56 begin
57  readln(n,m);
58  if m>sqr((n+1)shr 1) then
59   begin
60    writeln(0);
61    halt;
62   end;
63  dfs(0,1,0);
64  for i:=1 to total do
65   f[1,fa[i].j,fa[i].l]:=1;
66  for i:=2 to n do
67   for j:=1 to total do
68    for l:=0 to ((n+1)shr 1)*(i-1) do
69     if f[i-1,fa[j].j,l]=0 then
70      continue
71     else
72      for k:=1 to total do
73       if fa[j].p and fa[k].j=0 then
74        inc(f[i,fa[k].j,l+fa[k].l],f[i-1,fa[j].j,l]);
75  for i:=1 to total do
76   ans:=ans+f[n,fa[i].j,m];
77  writeln(ans);
78 end.
时间: 2024-10-18 09:01:30

BZOJ1087 互不侵犯 题解的相关文章

bzoj1087 互不侵犯King 状压dp+bitset

题目传送门 题目大意:中文题面. 思路:又是格子,n又只有9,所以肯定是状压dp,很明显上面一行的摆放位置会影响下一行,所以先预处理出怎样的二进制摆放法可以放在上下相邻的两行,这里推荐使用bitset,否则会比较麻烦.然后dp的数组是f[ i ][ x ][ j ],表示第i行已经放置了x个国王,第 i 行的状态是 j .同时预处理出对于每一种二进制位,可以增加几个国王,计做cnt[ j ],所以得到 if(mp[ s ][ j ]) f[ i +1 ][x +cnt[ j ]][ j ]+=f

BZOJ1087:[SCOI2005]互不侵犯——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1087 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sample Input 3 2 Sample Output 16 —————

bzoj1087互不侵犯King(状压)

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1087 简单的状压dp.但是wa了好几发.注意long long. 注意0和0的连边.而且不能连成两条,所以放在外面写. #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=15,M=1<<9; int n,m,lm,list[M+5

BZOJ1087=Codevs2451=洛谷P1896&amp;P2326互不侵犯

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2885  Solved: 1693[Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K &

BZOJ1087:[SCOI2005]互不侵犯King(状压DP)

[SCOI2005]互不侵犯King Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sample Input 3 2 Sample Output 16 分析: 经典的状压DP题目,可我竟然调了很长时间都没对,后来发现是DP枚举范围错

bzoj1087【SCOI2005】互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2405  Solved: 1413 [Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击.共同拥有多少种摆放方案. 国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 仅仅有一行,包括两个数N.K ( 1 <=N <=9, 0 <

【题解】[SCOI2005] 互不侵犯 (状压DP)

[SCOI2005] 互不侵犯 终于懂一点状压DP了… 用一个数的二进制形式表示一整行的状态,比如 18(1010)表示第一列和第三列有国王. 然后用&判断是否可行: if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;1code: #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>

SCOI2005互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1499  Solved: 872[Submit][Status] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N

C++之路进阶——状态压缩dp(互不侵犯)

2451 互不侵犯 2005年省队选拔赛四川 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入描述 Input Description 只有一行,包含两个数N,K ( 1 <=N <=9,  0 <= K <= N * N) 输出描述 Output Desc