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. 【最大流】【HDU3572】Task Schedule

    题意: 有N个事件,M台机器.事件有开始时间,持续时间,要在结束时间之前完成,问是否能完成所有事件? 非自己思考出来的 建图:把每个任务和每一天都看做一个点,添加源点和汇点.源点与每个任务之间连一条边 ...

  2. 【并查集+拓扑排序】【HDU1811】【Rank of Tetris】

    题意:给你3种关系 A=B,A>B,A<B 问是否排名方式唯一,或者存在矛盾 解 1.读入数据先处理 =号 用并查集的祖先作为代表元素,其他儿子节点都等于跟这个点重叠. 再读入 '< ...

  3. DSOframer 的简单介绍和资源整理

    DSOframer 是微软提供一款开源的用于在线编辑 Word. Excel .PowerPoint 的 ActiveX 控件.国内很多著名的 OA 中间件,电子印章,签名留痕等大多数是依此改进而来的 ...

  4. sqlyog绿色破解版

    http://pan.baidu.com/s/1mghyUrY 下载地址

  5. iOS 类管理

    CocoaPods安装和使用教程 Code4App 原创文章.转载请注明出处:http://code4app.com/article/cocoapods-install-usage 目录 CocoaP ...

  6. Ecside基于数据库的过滤、分页、排序

    首先ecside展现列表.排序.过滤(该三种操作以下简称为 RSF )的实现原理完全和原版EC一样, 如果您对原版EC的retrieveRowsCallback.sortRowsCallback.fi ...

  7. linux命令学习03-grep

    实例1.查找某个进程 #ps -ef | grep ssh root 1771 1 0 12:07 ? 00:00:00 /usr/sbin/sshdroot 2362 1771 0 16:34 ? ...

  8. python--执行文件的绝对路径

    1.__file__属性对应文件名. 2.os.path.realpath(__file__)这样就可以得到文件的绝对路径.

  9. 论山寨手机与Android联姻的技术基础 【序】

    山寨手机的兴起,离不开 MTK(联发科).MTK为手机制造提供了一揽子解决方案,其中既包括硬件,也包括软件.软件方面最重要的,是操作系统.MTK方案的软件的稳定性非常高,一方面是因为其硬件系统变化不大 ...

  10. java线程管理

    java线程管理 参见: http://harmony.apache.org/subcomponents/drlvm/TM.html 1. 修订历史 2. 关于本文档 2.1. 目的 2.2. 面向的 ...