【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP

经典状压DP.

f[i][j][k]=sum(f[i-1][j-cnt[k]][k]); cnt[i]放置情况为i时的国王数量

前I行放置情况为k时国王数量为J

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 #define N 1<<9
 5 long long ans;
 6 int n,m;
 7 int ok_1[N],cnt[N];
 8 int ok_2[N][N];
 9 long long  dp[10][9*9+10][N];
10 void init()
11 {
12     int sum;
13     for (int i=0;i<(1<<n);i++)
14     {
15         if ((i&(i<<1))==0 && (i&(i>>1))==0)
16         {
17             sum=0;
18             for (int j=i;j;j>>=1)    sum+=(j&1);
19             cnt[i]=sum; ok_1[i]=1;
20         }
21         for (int i=0;i<(1<<n);i++)
22             if (ok_1[i])
23                 for (int j=0;j<(1<<n);j++)
24                     if (ok_1[j])
25                         if ((i&j)==0 && (i&(j>>1))==0 && (i&(j<<1))==0)
26                             ok_2[i][j]=1;
27     }
28 }
29 int main()
30 {
31     scanf("%d%d",&n,&m);
32     init();
33     for (int i=0;i<(1<<n);i++) if (ok_1[i]) dp[1][cnt[i]][i]=1;
34     for (int i=2;i<=n;i++)
35         for (int j=0;j<(1<<n);j++)
36             if (ok_1[j])
37                 for (int k=0;k<(1<<n);k++)
38                     if (ok_1[k])
39                         if (ok_2[j][k])
40                             for (int l=cnt[k];l+cnt[j]<=m;l++)
41                                 dp[i][l+cnt[j]][j]+=dp[i-1][l][k];
42     for (int i=0;i<(1<<n);i++)
43         ans+=dp[n][m][i];
44     printf("%lld\n",ans);
45     return 0;
46 }


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

时间: 2024-10-29 19:06:19

【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP的相关文章

[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$就是把状态压缩成二进制数,利用二进制的位运算改进算法的一种方法

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 互不侵犯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

【题解】[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>

BZOJ 1087 SCOI 2005 互不侵犯King 状压DP

题目大意:一个国王可以攻击到旁边8个位置的格子,现在给出一个N*N的方格,向其中放k个国王,问有多少中摆放方法. 思路:状压DP,f[i][j][k],其中i是行数,j是状态,k是已经取了多少国王.然后暴力枚举状态,看相邻两行之间有没有冲突,若没有冲突,那么就转移. 注意要开long long CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>

[SCOI2005]互不侵犯(状压Dp)

题目 原题 Solution 看到数据范围就可以想到状压,然后你就可以直接转移就好了? #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<iostream> #include<queue> #include<algorithm> #define ll long long #define file(a) freo

[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

[bzoj1087] [SCOI2005]互不侵犯King

http://www.lydsy.com/JudgeOnline/problem.php?id=1087 一个n*n的棋盘,要在上面放国王,每个国王占领周围3*3的土地,求放置K个国王的方案数量. 一开始感觉结论题就打了个表,打一个8的表只要一两分钟??,虽然说n<=9,但是9的估计要很久...说不定考试那几个小时都打不完. 说说正解吧. 考虑壮压dp,如果按照一个个位置dp需要记录轮廓线以及左上角那个位置的情况,但是显然我们不需要那么复杂. 情况数2^9=512   预先处理好  每种情况是否

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