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则互不攻击,方案可行.对于每种方案,则用递推来 ...
随机推荐
- Dynamics Webservice Call with Credential
Dynamics Webservice call with credential /// <summary> ///WebServiceHelper 的摘要说明 /// </summ ...
- CSS从大图片上截取小图标的操作
注:图片名称(tabicons.png)每个小图标width:18px;height:18px从左上角坐标为(-0px;-0px;); 例如第一个对号的坐标为(-0px;-0px;)第二个加号的图标为 ...
- C++学习基础五之函数参数——形参
一.理论部分 C++中函数形参主要分为两类,如图1所示, 图1 总结: 一.当函数参数为非引用形参时,传进函数体内的是实参的拷贝,(注意,对于基本类型而言,拷贝的是实参的值,对于指针而言拷贝的是实参的 ...
- swift 当协议遇见了泛型
由于泛型比较简单,并没有单独拿出来介绍!我们在定义函数的时候,有时候只是由于参数或者返回值类型不同,而具体的实现过程是一模一样的,这个时候我们就可以定义泛型函数而使可以传入不同的参数类型: func ...
- NK3C开发要点
1.业务逻辑:文档, 2.后端资料 框架:spring + mybatis + maven + Shiro + 数据库(Oracle.SQL Server.MySQL) 分层:nmodel,ndal, ...
- yum 介绍
yum是一个用于管理rpm包的后台程序,用python写成,可以非常方便的解决rpm的依赖关系.在建立好yum服务器后,yum客户端可以通过 http.ftp方式获得软件包,并使用方便的命令直接管理. ...
- python默认的是17位小数的精度,但是这里有一个问题,就是当我们的计算需要使用更高的精度(超过17位小数)的时候该怎么做呢?
1. 使用格式化(不推荐) 1 2 3 >>> a = "%.30f" % (1/3) >>> a '0.3333333333333333148 ...
- java如何得到GET和POST请求URL和参数列表(转)
在servlet中GET请求可以通过HttpServletRequest的getRequestURL方法和getQueryString()得到完整的请求路径和请求所有参数列表,POST的需要getPa ...
- Javascript调用ActiveX示例
Javascript调用ActiveX示例 写一个ActiveX控件比如叫做MyNameSpace.SecreteInfo,安装在客户机器上,这样可以通过c++获取到机器的几乎任何信息. 在网 ...
- Java日志系统框架的设计与实现
推荐一篇好的文章介绍java日志系统框架的设计的文章:http://soft.chinabyte.com/database/438/11321938.shtml 文章内容总结: 日志系统对跟踪调试.程 ...