SCOI2005互不侵犯King

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1499  Solved: 872
[Submit][Status]

Description

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

Input

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

方案数。

Sample Input

3 2

Sample Output

16

HINT

Source

题解:

终于A了这道题。。。

其实意识到对安放的国王总个数有限制,那就应该是DP了

又因为是在棋盘上,所以以每行为状态进行转移

又因为n很小,所以状压DP。。。

主要是做一些预处理

代码:

 1 var  tot,n,i,j1,j2,j,k,l:longint;
 2      s:ansistring;
 3      ans:int64;
 4      a:array[0..1000,0..1000] of boolean;
 5      f:array[0..10,0..1000,0..100] of longint;
 6      can:array[0..1000] of boolean;
 7      calc:array[0..1000] of longint;
 8 function check(x,y:longint):boolean;
 9  var s1,s2:ansistring;
10      i:longint;
11   begin
12     s1:=binstr(x,n);
13     s2:=binstr(y,n);
14     for i:=1 to n do
15      if (s1[i]=‘1‘) and ((s2[i-1]=‘1‘) or (s2[i]=‘1‘) or (s2[i+1]=‘1‘)) then exit(false);
16     exit(true);
17   end;
18 function cann(x:longint):boolean;
19  var s:ansistring;
20      i:longint;
21   begin
22     s:=binstr(x,n);
23     for i:=2 to n do if (s[i]=‘1‘) and (s[i]=s[i-1]) then exit(false);
24     exit(true);
25   end;
26
27 procedure init;
28  begin
29    readln(n,k);
30    tot:=1<<n-1;
31    for i:=0 to tot do
32     begin
33       calc[i]:=0;
34       s:=binstr(i,n);
35       for j:=1 to n do if s[j]=‘1‘ then inc(calc[i]);
36     end;
37    fillchar(f,sizeof(f),0);
38    for i:=0 to tot do f[1,i,calc[i]]:=1;
39    for i:=0 to tot do
40     if cann(i) then can[i]:=true;
41   for i:=0 to tot do
42    if can[i] then
43     for j:=0 to tot do
44      if can[j] then
45       if check(i,j) then a[i,j]:=true;
46   //for i:=1 to tot do writeln(can[i],‘ ‘,calc[i]);
47  end;
48 procedure main;
49  begin
50    for i:=2 to n do
51      for j1:=0 to tot do
52       if can[j1] then
53        for l:=calc[j1] to k do
54         for j2:=0 to tot do
55          if (can[j2]) and (a[j1,j2]) then
56           inc(f[i,j1,l],f[i-1,j2,l-calc[j1]]);
57   // for i:=1 to n do
58   //  for j:=0 to tot do
59   //   for l:=1 to n do writeln(f[i,j,l]);
60    ans:=0;
61    for i:=0 to tot do if can[i] then inc(ans,f[n,i,k]);
62    writeln(ans);
63   end;
64 begin
65   assign(input,‘input.txt‘);assign(output,‘output.txt‘);
66   reset(input);rewrite(output);
67   init;
68   main;
69   close(input);close(output);
70 end.                          

SCOI2005互不侵犯King,布布扣,bubuko.com

时间: 2024-08-05 07:06:19

SCOI2005互不侵犯King的相关文章

[SCOI2005]互不侵犯King

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

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------

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枚举范围错

[Bzoj1083][SCOI2005]互不侵犯king(状压dp)

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

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

Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sample Input 3 2 Sample Output 16 HINT Source Solution 状压$dp$就是把状态压缩成二进制数,利用二进制的位运算改进算法的一种方法

洛谷 P1896 [SCOI2005]互不侵犯King

题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) 输出格式: 所得的方案数 输入输出样例 输入样例#1: 3 2 输出样例#1: 16 #include<cstdio> #include<cstring> #include<ios

【BZOJ 1087】[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 同学很早之前打表过了,orz 这题正解状压DP,f[i][s][k]表示第i行上一行的状态为S,选了k个 预处理出所有

【BZOJ】1087: [SCOI2005]互不侵犯King

[算法]状态压缩型DP [题解]http://www.cnblogs.com/xtx1999/p/4620227.html (orz) #include<cstdio> #include<algorithm> using namespace std; const int maxn=10,e2=530; long long f[maxn][e2][maxn*maxn]; int n,mk,num[e2],king[e2],ok[e2][e2]; bool selfcheck(int

[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