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则互不攻击,方案可行.对于每种方案,则用递推来 ...
随机推荐
- 用通俗易懂的大白话讲解Map/Reduce原理
Hadoop简介 Hadoop就是一个实现了Google云计算系统的开源系统,包括并行计算模型Map/Reduce,分布式文件系统HDFS,以及分布式数据库Hbase,同时Hadoop的相关项目也很丰 ...
- Ms sql将首字母大写
--辅助表 create table a ( a int ) declare @b int begin insert into a values(@b) end; go --表数据 ),id int) ...
- $.when().then()
当两个Ajax请求是成功的则执行函数myFunc,如果任一个有错误则执行myFailure. $.when($.ajax("/page1.php"), $.ajax("/ ...
- myeclipse 在mac中字体模糊问题解决方案
找到文件:/Applications/MyEclipse 2014/MyEclipse 2014.app/Contents/Profile/myeclipse.app/Contents/Info.pl ...
- 在IIS6上部署MVC站点,Nhiernate数据库底层
服务器环境要求: Windows 2003 server + IIS6.0 1.必须安装.net framework 4.0, MVC 2.最好能安装.net framework 的sp1, 我们服务 ...
- javascript 函数执行上下文
在js里,每个函数都有一个执行的上下文,我们可以通过this来访问. 如: 全局函数 function test(){ var local = this; } 我们发现local等于window(do ...
- 程序的删除kill、killall
发送信号给程序,或者列出信号集 SYNOPSIS kill [-s SIGNAL | -SIGNAL] PID... kill -l [SIGNAL]... 1.信号操 ...
- 如何让我们的VMware虚拟机上网——转载
一.必须检查你的windows系统的VMware DHCP Service 和VMware NAT Service这个两个服务是否启动.如果未启动请启动. 1,在开始windows里面输入servic ...
- Appium学习路-打包apk和ipa篇
间隔这么长时间再去写Appium的学习篇是有原因的,因为在想要用appium测试ios时,发现appium只能测试debug版本的ipa包.然后就需要自己去学习打包了啊.然后就对xcode各种不了解, ...
- Bash Shell实用快捷键
Ctrl-D 相当于Del键,即删除光标所在处的字符 Ctrl-E 相当于End键,即将光标移动到本行末尾 Ctrl-K 用于删除从光标处开始到结尾处的所有字符 Ctrl-L 清屏,相当于clear命 ...