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.."] ]
#include<iostream> #include<cmath> using namespace std; class Queen{ friend int nQueen(int); private: bool Place(int k); void Backtrack(int t); int n, //皇后的个数 *x; //当前解x[i] int sum; //当前已找到的可行方案数 }; bool Queen::Place(int k) //判断第K行的x[k]的可行性 { for(int i=1;i<k;i++) if((x[k]==x[i])||abs(i-k)==abs(x[i]-x[k]))return false; return true; } void Queen::Backtrack(int t) { if(t>n)sum++; else for(int i=1;i<=n;i++){ x[t]=i; if(Place(t))Backtrack(t+1); } } int nQueen(int n) { Queen X; //初始化 X.n=n; X.sum=0; int *p=new int [n+1]; for(int i=0;i<=n;i++) p[i]=0; X.x=p; X.Backtrack(1); delete [] p; return X.sum;}
#include<iostream> #include<string> #include<vector> using namespace std; class Solution { public: vector<vector<string> > solveNQueens(int n) { // Note: The Solution object is instantiated only once and is reused by each test case. vector<vector<string> > ret; this->columns=vector<int>(n,0); this->principal_diagonals=vector<int>(2*n,0); this->counter_diagonals=vector<int>(2*n,0); vector<int> C(n,0); //C[i]表示第i行皇后所在列的编号 DFS(0,C,ret); return ret; } private: //三个变量用于剪枝 vector<int> columns; //表示已经放置的皇后占据了哪些列 vector<int> principal_diagonals; //占据了哪些主对角线 vector<int> counter_diagonals; //占据了哪些副对角线 void DFS(int row,vector<int> &C,vector<vector<string> > &ret){ const int N =C.size(); if(row==N){ vector<string> solution; for(int i=0;i<N;++i){ string s(N,'.'); for(int j=0;j<N;++j){ if(j==C[i])s[j]='Q'; } solution.push_back(s); } ret.push_back(solution); return; } for(int j=0;j<N;++j){ //一列一列的验证 坐标为(raw,j) const bool ok=columns[j]==0 && principal_diagonals[j-row+N]==0 && //对角线怎么编号可以自己规划不同的方案但前后一致 counter_diagonals[row+j]==0; if(ok) { //合法,继续递归 C[row]=j; columns[j]=1; principal_diagonals[j-row+N]=1; counter_diagonals[row+j]=1; DFS(row+1,C,ret); //撤销动作 //c[row]=0; //没有必要,总是会继续覆盖,最终会被成功的一组覆盖。 columns[j]=principal_diagonals[j-row+N]=counter_diagonals[row+j]=0; } } } };
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
class Solution { public: int totalNQueens(int n) { this->col=vector<int>(n,0); this->principal=vector<int>(2*n,0); this->counter=vector<int>(2*n,0); int counts=0; vector<int> C(n,0); //C[i] 表示第i行皇后所在列编号 DFS(0,C,counts); return counts; } private: vector<int> col; //已经放置的皇后,占据了哪些列 vector<int> principal; //已经放置的皇后,占据哪些正对角线 vector<int> counter; //已经放置的皇后,占据了哪些负对角线 void DFS(int row,vector<int> &C,int &counts){ const int N=C.size(); if(row==N){ counts++; return; } for(int j=0;j<N;j++){ //一列列的验证,坐标为(row,j) bool ok=col[j]==0 && principal[j-row+N]==0 && counter[j+row]==0; if(ok){ C[row]=j; col[j]=1; principal[N+j-row]=1; counter[j+row]=1; DFS(row+1,C,counts); //撤销动作 C[row]=0; col[j]=principal[N+j-row]=counter[row+j]=0; } } } };