N皇后问题(位运算实现)
本文参考Matrix67的位运算相关的博文。
顺道列出Matrix67的位运算及其使用技巧 (一) (二) (三) (四),很不错的文章,非常值得一看。
主要就其中的N皇后问题,给出C++位运算实现版本以及注释分析。
皇后问题很经典,就不再赘述问题本身,解决皇后问题,一般采用的都是深搜DFS+回溯的方法,按照行(列)的顺序枚举每一个可以放置的情况,然后进行冲突判断,当前的放置是否合法,合法就继续搜索下一层,不合法就搜索就回溯。直到,找到一个合法的解,每一层都有一个皇后并且不发生冲突,这时候,放置的方案数计1.
位运算也是采用的也是深搜加回溯的方法,但是优点在于使用位运算进行冲突的检测,这使代码简洁高效,而且还加快了运行速度。
下面的两张图来自Matrix67的(三):

depth 表示当前要进行搜索的层,row的二进制表示当前层二进制为1是冲突列,ld表示从右上角到左下角对角线冲突关系,rd表示的从左上角到右下角的冲突关系。
具体实现代码如下:
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std; const int N = ; // 求解N皇后, N不能超过int的bits
int upper_limit = ( << N) - ; // 111...1111 n bits
int ans = ; void test(int row, int ld, int rd) {
// 如果row的皇后还没有放满
if (row != upper_limit) {
// (row|ld|rd)表示行row,右上到左下ld,左上到右下rd对角线,为1则是不能放的位置, 取~后表示能放置的位置
// 因为是用的int 32位存的,所以N位向上的高位需要重新置成0
// 所以再和upper_limit取&操作,就提取出所有可以放置皇后的位置
int pos = upper_limit & ~(row | ld | rd); // while 循环枚举所有为1的位置,然后去放置皇后
while (pos != ) {
// 和树状数组的lowbit一样,提取出pos的二进制最后一个1所在的位置的值
// 也可以写成x & (x^(x-1))
int p = pos & (-pos); pos = pos ^ p; // 将p二进制为1的位置在pos中置为0
// row | p 把p二进制为1的位置放上皇后
// (ld | p) << 1 更新ld的下一层不能放的位置
// (rd | p) >> 1 更新rd的下一层不能放的位置
test(row|p, (ld|p) << , (rd|p) >> );
}
} else ans++; } int main() {
ans = ;
clock_t start, finish;
double duration;
start = clock();
test(, , );
finish = clock();
duration = (double)(finish-start) / CLOCKS_PER_SEC;
printf("Time is %lf\n", duration);
printf("共有多少种情况: %d\n", ans);
return ;
}
分析:
位运算版本确实在代码编写和时间效率上都相当棒
代码的关键部分,就在于处理row,ld,rd搜索时候的禁位变化
当处理超过int可表示位数时候,这时候就要抛弃整型,使用bitset或者位结构去做相关操作
N皇后问题(位运算实现)的更多相关文章
- [CODEVS1295]N皇后(位运算+搜索)
题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任 ...
- N皇后的位运算有感
N皇后很明显是一个NP-Hard问题,如果n足够大的话,在有限较短的时间内是很难得出答案的,但是注意到N皇后(笔者认为这类问题称为棋盘问题更为贴切),在n*n棋盘之上,每个点有且只有两种状态,这与电脑 ...
- 洛谷 1219:八皇后 (位运算 & DFS)
题目链接: https://www.luogu.org/problem/show?pid=1219#sub row:受上面的皇后通过列控制的位置 ld:受上面的皇后通过从右至左的斜对角线控制的位置 r ...
- 【位运算经典应用】 N皇后问题
说到位运算的经典应用,不得不说N皇后问题. 学过程序设计的都知道N皇后问题,没听过也没关系.很简单,最传统的的N皇后问题是这个样子的,给你一个n * n大小的board,让你放n个皇后(国际象棋),要 ...
- N皇后-位运算优化
N皇后问题 时间限制: 5 Sec 内存限制: 128 MB 题目描述 魔法世界历史上曾经出现过一个伟大的罗马共和时期,出于权力平衡的目的,当时的政治理论家波利比奥斯指出:“事涉每个人的权利,绝不应 ...
- N皇后解法以及位运算优化
N皇后解法以及位运算优化 观察棋盘,要求皇后之间不能处在同行同列同一条斜线,求使得每行都有一个皇后的放置方法共有多少种. 每尝试放置一个皇后,都可以把该位置所在的行.列标号用一个数组标记,含义表示该行 ...
- N皇后问题 --使用位运算解决
关键位运算 x & (-x) 取得最低位1 x & (x-1) 去掉最低位1 class Solution(object): def totalNQueens(self, n): &q ...
- JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- BZOJ 1087 互不侵犯King (位运算)
题解:首先,这道题可以用位运算来表示每一行的状态,同八皇后的搜索方法,然后对于限制条件不相互攻击,则只需将新加入的一行左右移动与上一行相&,若是0则互不攻击,方案可行.对于每种方案,则用递推来 ...
随机推荐
- 【knowledgebase】不要在一个很大的RDD上调用collect
如果一个RDD很大以至于它的所有元素并不能在driver端机器的内存中存放下,请不要进行如下调用: val values = myVeryLargeRDD.collect() collect将尝试 ...
- 公网访问COSBench controller页面实现方法
总体实现思路:公网域名+nginx代理功能 条件: COSBench部署完毕,修改cosbench配置文件并启动,将127.0.0.1修改为本机IP,如:192.168.63.190 部署对外公网可以 ...
- 解决Windows8下Cisco Systems VPN Client的Reason 442: Failed to Enable Virtual Adapter错误
Windows8下使用Cisco Systems VPN Client创建的Cisco IPSec VPN无法连接,提示Reason 442: Failed to Enable Virtual Ada ...
- Oracle 表分区
从以下几个方面来整理关于分区表的概念及操作: 表空间及分区表的概念 表分区的具体作用 表分区的优缺点 表分区的几种类型及操作方法 对表分区的维护性操作 1.表空间及分区表的概念 表空间: 是一个或多个 ...
- android开发--布局三(微信布局)
微信主界面 我们布局应该从局来看,如上图,我们可以分为三个大的LinearLayout,再从LinearLayout嵌套其它布局,从而做出界面 文件 主界面代码: <LinearLayout x ...
- 使用虚幻引擎中的C++导论(三-反射系统与迭代器)
使用虚幻引擎中的C++导论(三) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如果有不 ...
- 【转载】Fast Inserts to PostgreSQL with JDBC and COPY FROM
source: http://rostislav-matl.blogspot.com/2011/08/fast-inserts-to-postgresql-with-jdbc.html Thanks ...
- "Asp.Net Web Api MediaTypeFormatter Error for x-www-formurlencoded data" 解决方法
遇到标题中所说的问题原因是使用 jQuery AJAX 以 POST 方式调用 Asp.Net Web API .解决办法请看以下代码中有注释的部分. public static class WebA ...
- LinQ 高级查询
高级查询 模糊查(包含):.Contains(name) 开头:.StartsWith(name) 结尾:.EndsWith(name) 个数:.Count() 最大值:Max(r => r.p ...
- Python UTF8 读取文件
严禁伸手党: