【位运算经典应用】 N皇后问题
说到位运算的经典应用,不得不说N皇后问题。
学过程序设计的都知道N皇后问题,没听过也没关系。很简单,最传统的的N皇后问题是这个样子的,给你一个n * n大小的board,让你放n个皇后(国际象棋),要满足任意两个皇后不能在一条水平线上,不能在一条垂直线上,也不能在一条45度的斜线上。听起来似乎和数独挺像,其实N皇后的条件更苛刻,除了水平垂直线外,数独只有两条对角线,而N皇后有很多条斜线,这点需要注意。
为了判断程序的正确性,正好leetcode上有道题可以测试N-Queens II,也是最经典的N皇后问题,给出n求得摆法的数量。
常规解法
一个很显而易见的解法是递归求解,从上到下一行一行摆下去,并且记录每行摆的位置,因为下一行摆放的位置要根据上面的摆放情况来确定。这里我们定义了一个pos数组,pos[1]的值表示摆在第一行的皇后所在的列,pos[2]的值表示摆在第二行的皇后所在的列,以此类推,所以摆到第n行时,上面摆放的皇后的位置就可以很容易地得到,从而可以进行判断(该行什么位置可以摆放)。
当摆放到第r行时,我们遍历该行所有的n个位置,判断每个位置(r行c列)是否可以摆放,需要与前面摆放的每个皇后比较,是否在一条水平线上(这是不可能的),是否在一条垂直线上,是否在一条斜线上:
function check(r, c) {
for (var i = 1; i < r; i++) {
if (Math.abs(i - r) === Math.abs(pos[i] - c)) // 一条斜线上
return true;
if (c === pos[i]) // 一条竖直线上
return true;
}
return false;
}
整个代码也就显而易见了:
var pos;
function check(r, c) {
for (var i = 1; i < r; i++) {
if (Math.abs(i - r) === Math.abs(pos[i] - c)) // 一条斜线上
return true;
if (c === pos[i]) // 一条竖直线上
return true;
}
return false;
}
function dfs(r, n) {
if (r === n + 1)
return 1;
var ans = 0;
for (var i = 1; i <= n; i++) {
if (check(r, i)) continue;
pos[r] = i;
ans += dfs(r + 1, n);
}
return ans;
}
var totalNQueens = function(n) {
pos = [];
return dfs(1, n);
};
位运算解法
在读下文前,请先阅读【位运算经典应用】标志位与掩码会事半功倍。
位运算解法,递归是避免不了的,能优化的在于check()函数部分。
假设一个4 * 4的board,我们在第一行第三列上摆了个皇后,其实它已经把第一行之后的6个位置给ko掉了:
- - o -
- X X X
X - X -
- - X -
我们用flag=2(1<<2)记录第一行摆下的这个位置,在第二行中,很显然(1<<2)这个位置已经不能摆了,而(2<<1)这个位置也不能摆,(2>>1)这个位置也不能摆。如果要在第二行右起第1个摆下皇后,我们用flag2=1(1<<1)记录这个决定,我们只需用flag2和以上算出来的不能摆的位置去做个与运算,看看有没有冲突即可。结果(2>>1)&(1<<1)得到了非0的数,表示两者冲突,所以该位置摆放失败。
假设我们接着在第二行左起第一个摆放了皇后,对于第三行的摆放来说,第一行摆的皇后对它还是有影响的,比如它不能摆在第三行左起第一个位置,因为(2<<2)&(1<<4)!==0,冲突。而(2<<2)正是在第二排摆放决策中(2<<1)<<1。看到这里你也许应该有了思路,没错,我们可以维护三个数,l, r, c, 用来表示该行被右上角斜线,左上角斜线,正上方直线所影响而不能摆放的位置。三个数每次与欲摆放的位置作与运算,求解是否冲突,如没有,l和r分别左移右移后继续递归。
function dfs(l, r, c, index, n) {
if (index === n)
return 1;
var ans = 0;
for (var i = 0; i < n; i++) {
var tmp = 1 << i;
if ((tmp & l) || (tmp & r) || (tmp & c)) continue;
ans += dfs((tmp | l) << 1, (tmp | r) >> 1, tmp | c, index + 1, n);
}
return ans;
}
var totalNQueens = function(n) {
return dfs(0, 0, 0, 0, n);
};
【位运算经典应用】 N皇后问题的更多相关文章
- Java位运算经典实例
一 源码.反码.补码 正数的源码.反码.补码相同,例如5: 5的源码:101 5的反码:101 5的补码:101 负数的源码.反码.补 ...
- N皇后-位运算优化
N皇后问题 时间限制: 5 Sec 内存限制: 128 MB 题目描述 魔法世界历史上曾经出现过一个伟大的罗马共和时期,出于权力平衡的目的,当时的政治理论家波利比奥斯指出:“事涉每个人的权利,绝不应 ...
- JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- 位运算总结&拾遗
JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识 ...
- leetcode - 位运算题目汇总(下)
接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...
- 【C语言】位运算
编写一个函数getbits,从一个16位的单元中取出某几位(即该几位保留原值,其余位0).函数调用形式为getbits(value,n1,2).----简单题目遇到想不到的问题 c语言位运算经典问题: ...
- N皇后问题(位运算实现)
本文参考Matrix67的位运算相关的博文. 顺道列出Matrix67的位运算及其使用技巧 (一) (二) (三) (四),很不错的文章,非常值得一看. 主要就其中的N皇后问题,给出C++位运算实现版 ...
- [CODEVS1295]N皇后(位运算+搜索)
题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任 ...
- C语言位运算、移位运算 经典示例
概述: C语言的位级运算可以运用到任何“整数”的数据类型上,如char.short.int.long.long long.或者unsigned这样的限定词.基本的位运算有与.或.非.异或等等. C语言 ...
随机推荐
- druid连接池异常
在从excel导入10W条数据到mysql中时,运行一段时间就会抛这个异常,连接池问题 org.springframework.transaction.CannotCreateTransactionE ...
- redis k-v数据库、高速缓存、消息队列代理
Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的 ...
- 0005 《SQL必知必会》笔记01-SELECT语句
1.SELECT基本语句: SELECT 字段名1,···,字段名n FROM 表名 2.检索所有字段,用"*"替换字段名,这会导致效率低下 SELECT * FROM 表名; 3 ...
- bootstrap简单的过一遍
注:.xxxx 表示类(class=xxxx) <h1>到<h6>均可使用.另外还提供了.h1到.h6的class .lead可以让段落突出显示 <small> ...
- HashMap的key可以是可变的对象吗???
大家都知道,HashMap的是key-value(键值对)组成的,这个key既可以是基本数据类型对象,如Integer,Float,同时也可以是自己编写的对象,那么问题来了,这个作为key的对象是否能 ...
- Linux dd
一.简介 二.实例 1)复制二进制文件指定章节 iflag=skip_bytes bs= count= of=test 2)修改二进制文件指定章节 oflag=seek_bytes bs= count ...
- Android Studio中使用android:src="@drawable/ic_launcher"报错
今天尝试着安装了Android Studio,界面确实不错,列表什么的也改了很多. 然后新建工程,习惯性在activity_main那里加上一段代码测试看看: <ImageView androi ...
- Binary search tree
#ifndef __TREE_H #define __TREE_H #include <iostream> template<typename T> class TreeNod ...
- Virtualbox配置双网卡
hadoop内部的虚拟机群,使用Host-Only 因为我之前一直是把三台虚机配置成桥接网络,可以同时上网又可以互通,但有一段时间,网络一直不通畅,造成hadoop核心进程一直关闭. 最后为了稳定起见 ...
- DPM检测模型 训练自己的数据集 读取接口修改
(转载请注明作者和出处 楼燚(yì)航的blog :http://www.cnblogs.com/louyihang-loves-baiyan/ 未经允许请勿用于商业用途) 本文主要是针对上一篇基于D ...