51. N-Queens (Array; Back-Track, Bit)
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."], ["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
思路I:按行递归,在每个递归过程中按列循环,此时可能会有多种选择,所以使用回溯法。
注意每个小对角线也要check。
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
if(n==) return result;
string str="";
for(int i = ; i< n; i++){ //construct "...."
str += '.';
}
vector<string> item(n,str);
backTracking(n, item, );
return result;
}
void backTracking(int n, vector<string>& item, int depth){ //depth is the line number
if(depth==n){
result.push_back(item);
return;
}
for(int i = ; i < n; i++){ //traverse column
item[depth][i] = 'Q';
if(check(n,item, depth, i)) backTracking(n,item,depth+);
item[depth][i] = '.'; //back track
}
}
bool check(int n, vector<string>& item, int i, int j){
int k;
//check line to see if there's repetition
for(k = ; k < n; k++){
if(k==i) continue;
if(item[k][j]=='Q') return false;
}
//check column to see if there's repetition
for(k = ; k < n; k++){
if(k==j) continue;
if(item[i][k]=='Q') return false;
}
//check upper left
for(k = ; i-k >= && j-k>=; k++){
if(item[i-k][j-k]=='Q') return false;
}
//check lower right
for(k = ; i+k <n && j+k<n; k++){
if(item[i+k][j+k]=='Q') return false;
}
//check upper right
for(k = ; i-k >= && j+k<n; k++){
if(item[i-k][j+k]=='Q') return false;
}
//check lower left
for(k = ; i+k <n && j-k>=; k++){
if(item[i+k][j-k]=='Q') return false;
}
return true;
}
private:
vector<vector<string>> result;
};
思路II:对思路I,简化check
首先,对于每一行,不用check,因为在一个for循环中已经用回溯规避了重复。
对于列,我们用一个一维数组标记Q的位置,下标为行号,值为出现Q的列号。
对于对角线的check,check每一列Q所在的(row2,column2) 与当前点(row1, column1)是否满足|row1-row2| = |column1 - column2|,满足表示在一个对角线上。
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
if(n==) return result;
vector<int> flag(n,-); //每行的Q出现在哪列
backTracking(n, flag, );
return result;
}
void backTracking(int n, vector<int>& flag, int depth){ //depth is the line number
if(depth==n){
vector<string>item(n, string(n,'.')); //initialize as all '.'
for(int i = ; i < n; i++)
item[i][flag[i]] = 'Q';
result.push_back(item);
return;
}
for(int i = ; i < n; i++){ //traverse column
if(check(n,flag, depth, i)) {
flag[depth] = i;
backTracking(n,flag,depth+);
flag[depth] = -; // back track
}
}
}
bool check(int n, vector<int>& flag, int i, int j){
for(int k = ; k < i; k++){
if(flag[k] < ) continue;//no Q in this column
if(flag[k]==j) return false;//check columns
if(abs(i-k)==abs(j-flag[k])) return false; //check cross lines
}
return true;
}
private:
vector<vector<string>> result;
};
思路III: 递归调用会有很多函数堆栈处理,参数拷贝,耗时耗内存,所以改用循环。思路还是back track,在没有答案的时候要回溯到上一行的Q位置之后的那个位置。
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
if(n==) return result;
vector<int> flag(n,-);
int i = , j = ;
while(!(i== && j==n)){
if(j==n){ //no valid Q in this line, back track
i--;
j = flag[i]+;
flag[i] = -;
continue;
}
if(i==n){ //find one solution
vector<string>item(n, string(n,'.')); //initialize as all '.'
for(int k = ; k < n; k++)
item[k][flag[k]] = 'Q';
result.push_back(item);
//back track
i--;
j = flag[i]+;
flag[i] = -;
continue;
}
if(check(n,flag, i, j)) {
flag[i] = j;
i++;
j = ;
}
else{
j++;
}
}
return result;
}
bool check(int n, vector<int>& flag, int i, int j){
for(int k = ; k < i; k++){
if(flag[k] < ) continue;//no Q in this column
if(flag[k]==j) return false;//check columns
if(abs(i-k)==abs(j-flag[k])) return false; //check cross lines
}
return true;
}
private:
vector<vector<string>> result;
};
思路IV:通过为操作继续简化状态变量,将一维数组简化为整型。通过状态row、ld、rd分别表示在列和两个对角线方向的限制条件下,当前行的哪些地方不能放置皇后。
举例说明:前三行放置了皇后

他们对第3行(行从0开始)的影响如下:
(1)列限制条件下,第3行的0、2、4列(紫色线和第3行的交点)不能放皇后,因此row = 101010
(2)左对角线限制条件下,第3行的0、3列(蓝色线和第3行的交点)不能放皇后,因此ld = 100100
(3)右对角线限制条件下,第3行的3、4、5列(绿色线和第3行的交点)不能放皇后,因此rd = 000111
~(row | ld | rd) = 010000,即第三行只有第1列能放置皇后。
在3行1列这个位置放上皇后,row,ld,rd对下一行的影响为:
row的第一位置1,变为111010
ld的第一位置1,并且向左移1位(因为左对角线对下一行的影响是当前位置向左一个),变为101000
rd的第一位置1,并且向右移1位(因为右对角线对下一行的影响是当前位置向右一个),变为001011
第4行状态如下图

class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
if(n==) return result;
mask = (<<n) - ; //Bit operation: 低n位置1
vector<string> cur(n, string(n,'.'));
backTracking(, , , cur, );
return result;
}
void backTracking(const int row, const int ld, const int rd, vector<string>& cur, int depth){ //depth is the line number
if(row==mask){ //find one solution
result.push_back(cur);
return;
}
int pos, p;
pos = mask & (~(row|ld|rd)); //pos置1的位置表示可以放置Q
while(pos){
p = pos & (~pos + );//Bit Operation: 获取pos最右边的1
pos = pos - p; //把pos最右边的1清0
setQueen(cur, depth, p, 'Q');
backTracking(row|p, (ld|p)<<, (rd|p)>>, cur, depth+); //iterate next line
setQueen(cur, depth, p, '.'); //back track
}
}
void setQueen(vector<string>& cur, int depth, int p, char val){
int col = ;
while(!(p&)){
p >>= ;
col++;
}
cur[depth][col]=val;
}
private:
vector<vector<string>> result;
int mask;
};
51. N-Queens (Array; Back-Track, Bit)的更多相关文章
- How to set the initial value of a select element using AngularJS ng-options & track by
原文: https://www.gurustop.net/blog/2014/01/28/common-problems-and-solutions-when-using-select-element ...
- 嵌入式 使用mp4v2将H264+AAC合成mp4文件
录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流: (2)将H26 ...
- window7 触屏操作相关
一.体系概述 1.Windows Touch Input 和 Gestures消息 Windows Touch消息特性 通过在执行期间的监听和解释来使能.下面的示例展示了Windows7 上消息是怎么 ...
- PHP array_multisort() 函数详解 及 二维数组排序(模拟数据表记录按字段排序)
一.先看最简单的情况. 有两个数组: $arr1 = array(1, 9, 5); $arr2 = array(6, 2, 4); array_multisort($arr1, $arr2); pr ...
- NumPy的详细教程
原文 http://blog.csdn.net/lsjseu/article/details/20359201 主题 NumPy 先决条件 在阅读这个教程之前,你多少需要知道点python.如果你想 ...
- Apache Spark源码走读之24 -- Sort-based Shuffle的设计与实现
欢迎转载,转载请注明出处. 概要 Spark 1.1中对spark core的一个重大改进就是引入了sort-based shuffle处理机制,本文就该处理机制的实现进行初步的分析. Sort-ba ...
- C语言解决八皇后问题
#include <stdio.h> #include <stdlib.h> /* this code is used to cope with the problem of ...
- 微信浏览器里location.reload问题
微信浏览器里location.reload问题会导致有时候post数据丢失.建议不要用此方式,尽量ajax方式获取或不要为了获取新的UI而刷新页面 2015-12-26 00:51:34array ( ...
- 使用mp4v2将H264+AAC合成mp4文件
录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流: (2)将H26 ...
- PHP数组排列
一.先看最简单的情况.有两个数组: $arr1 = array(1,9,5);$arr2 = array(6,2,4); array_multisort($arr1,$arr2); print_r($ ...
随机推荐
- 用过的sql 工具
sequel pro 港优创新 php myadmin 腾讯
- 有意思的bug
1. Xss攻击型的bug Xss攻击即跨站脚步攻击,通过插入恶意脚本 ,实现对用户浏览器的控制. Bug现象:新增物品时,物品名称输入一段JavaScript代码,在提交时此代码被执行.如:输入&l ...
- Java堆外内存之四:直接使用Unsafe类操作堆外内存
在nio以前,是没有光明正大的做法的,有一个work around的办法是直接访问Unsafe类.如果你使用Eclipse,默认是不允许访问sun.misc下面的类的,你需要稍微修改一下,给Type ...
- java实验——将100-300之间的素数输出
public class 实验1 { //将100-300之间的素数输出 /** * @param args */ public static void main(String[] args) { / ...
- 【HTTP】Fiddler 抓包工具
[HTTP]Fiddler(一) - Fiddler简介 [HTTP]Fiddler(二) - 使用Fiddler做抓包分析 [HTTP]Fiddler(三)- Fiddler命令行和HTTP断点调试
- sql isdate判断时间函数(小技巧)
isdate 是一个判断字符串是否为日期的函数,0代表所传入的字符串不是日期,1代表传入的参数是日期. select isdate('30/12/2014') ---0 第一个是 mdy --如 ...
- uva-10344
题意: 枚举23点,注意,数字也是可以枚举的,wa了一次 #include<stdio.h> #include<iostream> #include<sstream> ...
- leetcode191
public class Solution { public int HammingWeight(uint n) { var list = new List<uint>(); do { ; ...
- shiro用authc配置后登录成功后不能跳转到index页面
转自:https://ydoing.iteye.com/blog/2248188
- java Export Excel POI 转
最终选择用POI成功导出excel.总之很有用. http://www.cnblogs.com/xwdreamer/archive/2011/07/20/2296975.html http://poi ...