1. 题目:在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。
思路:用一个大小为n的数组path保存皇后的位置,i表示第i行,path[i]表示第i行皇后所处的列。这样,每一行都有一个皇后,即它们不处于同一行。为了保证不处于同一列,则path[i]!=path[j]。同样为了保证不处于同一对角线,则abs(i-j)!=abs(path[i]-path[j])。
递归全排列:
int totalNQueens(int n) {
int result=0;
vector<int> path;
for(int i=0;i<n;++i)
path.push_back(i);
Permutation(result,n,path,0);
return result;
}
void Permutation(int &result, int n, vector<int> &path, int j){
if(j==n){
if(Check(path,n))
result++;
return;
}
for(int i=j;i<n;++i){
int temp=path[i];
path[i]=path[j];
path[j]=temp;
Permutation(result,n,path,j+1);//固定住第j位,递归排列后面的j+1~n位。
temp=path[i];
path[i]=path[j];
path[j]=temp;
}
}
bool Check(vector<int> &path, int n){
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(i!=j)
if(abs(i-j)==abs(path[i]-path[j]))
return false;
}
}
return true;
}
2. n-queens-ii
深度优先搜索:
int totalNQueens(int n) {
int result=0;
vector<int> path;
dfs(n,result,path,0);
return result;
}
void dfs(int n, int &result, vector<int> &path, int j){
if(j==n){
++result;
return;
}
for(int i=0;i<n;++i){
path.push_back(i);
if(Check(path,j)) dfs(n, result, path, j+1);
path.pop_back();//恢复原状态
}
}
bool Check(vector<int> &path, int j){
for(int i=0;i<j;++i){
if(path[i]==path[j] || abs(i-j)==abs(path[i]-path[j]))
return false;
}
return true;
}
3. n-queens
深度优先搜索:
vector<vector<string> > solveNQueens(int n) {
vector<vector<string> > result;
vector<int> path;
NQueens(n,result,path,0);
return result;
}
void NQueens(int n, vector<vector<string> > &result, vector<int> &path, int j){
if(j==n){
vector<string> result_one;
for(int i=0;i<n;++i){
string temp(n,'.');
temp[path[i]]='Q';
result_one.push_back(temp);
}
result.push_back(result_one);
return;
}
for(int i=0;i<n;++i){
path.push_back(i);
if(Check(path,j))
NQueens(n,result,path,j+1);
path.pop_back();
}
}
bool Check(vector<int> &path, int j){
for(int i=0;i<j;++i){
if(path[i]==path[j] || abs(i-j)==abs(path[i]-path[j]))
return false;
}
return true;
}