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($ ...
随机推荐
- 杂项-自动化测试工具:Selenium(浏览器自动化测试框架)
ylbtech-杂项-自动化测试工具:Selenium(浏览器自动化测试框架) Selenium 是一个用于Web 应用程序测试的工具.Selenium 测试直接运行在浏览器中,就像真正的用户在操作一 ...
- file_get_contents是打工文件或URL获取内容的方法,比其稳定的还有curl_get_contents
相信使用过file_get_contents函数的朋友都知道,当获取的$url访问不了时,会导致页面漫长的等待,甚至还能导致PHP进程占用CPU达100%,因此这个函数就诞生了 分享一个实际在用的函数 ...
- sklearn中的metrics模块中的Classification metrics
metrics是sklearn用来做模型评估的重要模块,提供了各种评估度量,现在自己整理如下: 一.通用的用法:Common cases: predefined values 1.1 sklearn官 ...
- SVM的sklearn.svm.SVC实现与类参数
SVC继承了父类BaseSVC SVC类主要方法: ★__init__() 主要参数: C: float参数 默认值为1.0 错误项的惩罚系数.C越大,即对分错样本的惩罚程度越大,因此在训练样本中准确 ...
- Dividing Infinity - Distributed Partitioning Schemes
This is the second post in a series discussing the architecture and implementation of massively para ...
- Dep数据发布,推送
package com.cfets.ts.u.shchgateway.util; import com.cfets.cwap.s.stp.MessageUnit; import com.cfets.t ...
- Postman的基础使用
postman的基础功能,官方文档介绍的是相当啰嗦,所以笔者这里先简单介绍一下主界面,入门功能就都提到了.稍后我们再一一介绍基础功能的使用方法. Collections:在Postman中,Colle ...
- spring boot 整合MongoDB
参考 https://www.cnblogs.com/nbfujx/p/7999171.html
- 如何使用Python快速制作可视化报表----pyecharts
如何使用Python快速制作可视化报表 数据可视化能力已经越来越成为各岗位的基础技能.领英的数据报告显示,数据可视化技能在2017年中国最热门技能中排名第一. 就数据分析而言,可视化探索几乎是你正 ...
- delphi android路径 TPath 文件路径,文件管理
获取Android相关文档路径 delphi 新路径.文件功能 IOUtils单元,文件路径,文件管理 http://docwiki.embarcadero.com/RADStudio/Berlin/ ...