51. N-Queens (Array; Back-Track, Bit)

时间:2022-10-20 18:03:50

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

51. N-Queens (Array; Back-Track, Bit)

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分别表示在列和两个对角线方向的限制条件下,当前行的哪些地方不能放置皇后

举例说明:前三行放置了皇后

51. N-Queens (Array; Back-Track, Bit)

他们对第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行状态如下图

51. N-Queens (Array; Back-Track, Bit)

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)的更多相关文章

  1. How to set the initial value of a select element using AngularJS ng-options &amp&semi; track by

    原文: https://www.gurustop.net/blog/2014/01/28/common-problems-and-solutions-when-using-select-element ...

  2. 嵌入式 使用mp4v2将H264&plus;AAC合成mp4文件

    录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流: (2)将H26 ...

  3. window7 触屏操作相关

    一.体系概述 1.Windows Touch Input 和 Gestures消息 Windows Touch消息特性 通过在执行期间的监听和解释来使能.下面的示例展示了Windows7 上消息是怎么 ...

  4. PHP array&lowbar;multisort&lpar;&rpar; 函数详解 及 二维数组排序(模拟数据表记录按字段排序)

    一.先看最简单的情况. 有两个数组: $arr1 = array(1, 9, 5); $arr2 = array(6, 2, 4); array_multisort($arr1, $arr2); pr ...

  5. NumPy的详细教程

    原文  http://blog.csdn.net/lsjseu/article/details/20359201 主题 NumPy 先决条件 在阅读这个教程之前,你多少需要知道点python.如果你想 ...

  6. Apache Spark源码走读之24 -- Sort-based Shuffle的设计与实现

    欢迎转载,转载请注明出处. 概要 Spark 1.1中对spark core的一个重大改进就是引入了sort-based shuffle处理机制,本文就该处理机制的实现进行初步的分析. Sort-ba ...

  7. C语言解决八皇后问题

    #include <stdio.h> #include <stdlib.h> /* this code is used to cope with the problem of ...

  8. 微信浏览器里location&period;reload问题

    微信浏览器里location.reload问题会导致有时候post数据丢失.建议不要用此方式,尽量ajax方式获取或不要为了获取新的UI而刷新页面 2015-12-26 00:51:34array ( ...

  9. 使用mp4v2将H264&plus;AAC合成mp4文件

    录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流: (2)将H26 ...

  10. PHP数组排列

    一.先看最简单的情况.有两个数组: $arr1 = array(1,9,5);$arr2 = array(6,2,4); array_multisort($arr1,$arr2); print_r($ ...

随机推荐

  1. C&num;泛型代理、泛型接口、泛型类型、泛型方法

    //http://www.cnblogs.com/JeffreySun/archive/2012/11/14/2770211.html //http://www.baqima.com/a/2628.h ...

  2. POJ 1947 (树形DP&plus;背包&rpar;

    题目链接: http://poj.org/problem?id=1947 题目大意:树中各点都由一条边连接.问要弄出个含有m个点的(子)树,至少需要截去多少条边. 解题思路: 设dp[i][j]为i总 ...

  3. 【原】Nginx添加Content-MD5头部压测分析

    如需转载,必须注明原文地址,请尊重作者劳动成果. http://www.cnblogs.com/lyongerr/p/5048464.html 本文介绍了webbenck安装,但是最后使用的是ab工具 ...

  4. Aizu 2309 Sleeping Time DFS

    Sleeping Time Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...

  5. QuickSwitchSVNClient,快速完成SVN Switch的工具

    [开源]QuickSwitchSVNClient,快速完成SVN Switch的工具 在实际的开发中,我们一般使用SVN工具进行源代码的管理.在实际的产品开发中,根据项目的一些定制要求,往往需要对某一 ...

  6. apache无法启动报错No space left on device

    apache无法启动报错No space left on device 故障现象:apache无法启动ipcs信号量很多 # service httpd startStarting httpd : [ ...

  7. python中requests的用法总结

    requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到.可以说,Requests 完全满足如今网络的需求 本文全部来源于官方文档 http://docs ...

  8. 1095 Anigram单词

      基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的Anigram,例如单词 ...

  9. python - logging模块应用

    logging日志模块应用: import logging # logging.basicConfig( # #定义日志级别,共5个级别,默认级别为warning级别,所以debug和info级别不添 ...

  10. Oracle 存储过程了解

    简要记录存储过程语法与Java程序的调用方式 一 存储过程 首先,我们建立一个简单的表进行存储过程的测试 createtable xuesheng(id integer, xing_ming varc ...