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($ ...
随机推荐
-
C#泛型代理、泛型接口、泛型类型、泛型方法
//http://www.cnblogs.com/JeffreySun/archive/2012/11/14/2770211.html //http://www.baqima.com/a/2628.h ...
-
POJ 1947 (树形DP+背包)
题目链接: http://poj.org/problem?id=1947 题目大意:树中各点都由一条边连接.问要弄出个含有m个点的(子)树,至少需要截去多少条边. 解题思路: 设dp[i][j]为i总 ...
-
【原】Nginx添加Content-MD5头部压测分析
如需转载,必须注明原文地址,请尊重作者劳动成果. http://www.cnblogs.com/lyongerr/p/5048464.html 本文介绍了webbenck安装,但是最后使用的是ab工具 ...
-
Aizu 2309 Sleeping Time DFS
Sleeping Time Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...
-
QuickSwitchSVNClient,快速完成SVN Switch的工具
[开源]QuickSwitchSVNClient,快速完成SVN Switch的工具 在实际的开发中,我们一般使用SVN工具进行源代码的管理.在实际的产品开发中,根据项目的一些定制要求,往往需要对某一 ...
-
apache无法启动报错No space left on device
apache无法启动报错No space left on device 故障现象:apache无法启动ipcs信号量很多 # service httpd startStarting httpd : [ ...
-
python中requests的用法总结
requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到.可以说,Requests 完全满足如今网络的需求 本文全部来源于官方文档 http://docs ...
-
1095 Anigram单词
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的Anigram,例如单词 ...
-
python - logging模块应用
logging日志模块应用: import logging # logging.basicConfig( # #定义日志级别,共5个级别,默认级别为warning级别,所以debug和info级别不添 ...
-
Oracle 存储过程了解
简要记录存储过程语法与Java程序的调用方式 一 存储过程 首先,我们建立一个简单的表进行存储过程的测试 createtable xuesheng(id integer, xing_ming varc ...