Description

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

Input

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

Output

方案数。

Sample Input

3 2

Sample Output

16

首先这道题用到了名叫状压dp的算法

首先声明:这篇博客不适用于大神们!!!!!

看到互不侵犯的king这道题首先想到的是八皇后问题,但是发现和八皇后大不一样,因为八皇后是用的深搜的方法,但是由于根据国象的规则,一个棋盘能放的皇后要比国王少得多,所以DFS即可。

所以我们考虑其他的方法,因为国王的攻击范围很小,只有周围的一圈。但我们依然不能把所有的状态推出来(即使n<=9)。但我们可以发现只要确定了第一行,就可以将下面的用动规推出来。这样我们就可以用枚举的方式来做了。在枚举的同时,我们可以用二进制的方式来表示状态,这样较好比较,同时也可以压缩状态,这就是状压dp的思想。在这里可以模拟一下。

比如说n=5。 用1表示该格有国王,0反之。

1 1 1 1 1 这种情况显然是不存在的,我么就要把它排除掉。那么怎么排除呢?我们考虑用位运算的思想。将它 右移(>>)一位(因为国王的攻击范围只有1)。即 1 1 1 1 1再进行(&)运算,这样的返回值是1则出现冲突,再比如这种情况 1 0 1 0 1                                         1 1 1 1 1                                                                。                                1 0 1 0 1   这样的返回值是0,所以这种情况存在。而二进制我们可以直接用一个十进制数来表示。如 1 1 1 1 1 十进制是31,可以试一试计算 31&(31>>1)==1.而 1 0 1 0 1 十进制是21,

21&(21>>1)==0。比较时应该左移、右移都进行。另外我们还可以进行预处理。总状态数为 2^n-1,只进行循环即可,代码如下

int check2(int a)//一行自比
{
if(a&(a<<)) return ;
if(a&(a>>)) return ;
return ;
}
int get(int x)//计算状态为x,其中 1 的个数。
{
int tot=;
while(x){
if(x&)
tot++;
x=x>>;
}
return tot;
}int tot=(<<n)-;
for(int i=;i<=tot;i++)
if(check2(i)){
zt[++num]=i;//状态
gs[num]=get(i);//该状态含的国王的个数
}

接下来讲dp的过程——

int f[10] (i) [600] (j) [82] (k) {0};//i为行数,j为第j种状态,k为当前总国王数 f[i][j][k]表示第i行状态为第j种放置了k个国王的方案数。

另外的一种预处理如下,对比两行的状态,可以加速dp过程中的比较。

int check1(int a,int b)//两行对比
{
if(a&(b<<)) return ;
if(a&(b>>)) return ;
if(a&b)return ;//对比两行时就需要对比不移动时的状态,至于为什么,自行脑补
return ;
}
for(int i=;i<=num;i++)//pd[i][j]==1则表示i在上一行j在下一行,并且不冲突
for(int j=;j<=num;j++)
if(check1(zt[i],zt[j]))
pd[i][j]=pd[j][i]=;

主要的dp过程如下

for(int i=;i<n;i++)//循环行数,对应f数组中的行数(i)
for(int j=;j<=num;j++)//循环状态,对应f数组中的(j)
for(int k=;k<=m;k++)//循环国王数,对应数组中的(k)
if(f[i][j][k])
for(int q=;q<=num;q++)//循环i下一行的状态
if(pd[j][q]&&(k+gs[q]<=m))//满足条件就继续
f[i+][q][k+gs[q]]+=f[i][j][k];
long long int ans=;
for(int i=;i<=num;i++)//把第n行的所有状态的f值相加即为答案
ans+=f[n][i][m];

这就是主要的函数,其他的自己加上的吧,光复制标程是没有意义的!!

注意:f[0][1][0]=1  即初始的状态。

BZOJ 1087 互不侵犯king的更多相关文章

  1. BZOJ 1087 互不侵犯King 状态压缩DP

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1087 题目大意; 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国 ...

  2. BZOJ 1087 互不侵犯King (位运算)

    题解:首先,这道题可以用位运算来表示每一行的状态,同八皇后的搜索方法,然后对于限制条件不相互攻击,则只需将新加入的一行左右移动与上一行相&,若是0则互不攻击,方案可行.对于每种方案,则用递推来 ...

  3. BZOJ 1087 互不侵犯

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

  4. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  5. bzoj 1087 [SCOI2005]互不侵犯King 状态压缩dp

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Descripti ...

  6. BZOJ 1087:[SCOI2005]互不侵犯King(状压DP)

    [SCOI2005]互不侵犯King [题目描述] 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子 ...

  7. 1087: [SCOI2005]互不侵犯King

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4276  Solved: 2471[Submit][ ...

  8. 【状压dp】互不侵犯KING

    互不侵犯KING Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3866  Solved: 2264[Submit][Status][Discuss] ...

  9. BZOJ-1087 互不侵犯King 状压DP+DFS预处理

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2337 Solved: 1366 [Submit][ ...

随机推荐

  1. C#操作项目配置文件

    前言 对于项目配置文件的读取和修改,.net 提供了ConfigurationManager(位于System.Configuration命名空间) 和WebConfigurationManager( ...

  2. hive 函数学习

    NAME PRICE ---- ----- AAA 1.59 AAA 2.00 AAA 0.75 BBB 3.48 BBB 2.19 BBB 0.99 BBB 2.50 I would like to ...

  3. [Linked List]Remove Duplicates from Sorted List

    Total Accepted: 90247 Total Submissions: 254602 Difficulty: Easy Given a sorted linked list, delete ...

  4. 搜索+剪枝——运筹帷幄 (road.cpp)

    运筹帷幄 (road.cpp) [题目描述] 刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行. 已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表 ...

  5. 【转】Perl Unicode全攻略

    Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...

  6. box-shadow 给图片添加内部阴影

    box-shadow 是css3中定义的设置元素阴影的属性,其语法结构如下: <shadow> = inset? && <length>{2,4} && ...

  7. codeforces 702E Analysis of Pathes in Functional Graph 倍增

    题目链接 给一个图, 然后给出每条边的权值和一个k值. 让你求出从每个点出发, 走k次能获得的边权的和以及边权的最小值. 用倍增的思想, 求出每个点走一次能到达的点, 权值和以及最小值, 走两次..四 ...

  8. python 网络编程第四版

    使用SocketServer 模块来完成服务端编程 1.服务端代码如下: #!/usr/bin/python #!coding:utf-8 import SocketServer as sockets ...

  9. document.ready()的用法

    1.Jquery是优秀的Javascrīpt框架,$是jquery库的申明,它很不稳定(我就常遇上),换一种稳定的写法jQuery.noConflict(); jQuery(document).rea ...

  10. Python学习之编写登陆接口(Day1,作业一)

    作业一:编写登陆接口 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定(下次登陆还是锁定) 知识点:while循环,for循环,文件操作,if判断,列表操作 思路: 1.登陆,三次登陆失败,锁定 ...