解决N皇后问题分为以下几个步骤:
- 首先要定义出两个二维的数组,
一个是attack数组用于表示当前皇后已经占住的攻击范围,0代表可以放置皇后,1代表此地方不能放置皇后
一个是queen用于表示哪些点上皇后有皇后,当前位置为’.'代表此位置没有皇后,当前位置为’Q’代表有皇后,然后再进行初始化:
queen全部初始化为'.' attack全部初始化为0
下面写一下第一步的代码:
vector<vector<int>>attack;
vector<string>queen;
for(int i = 0; i<n;i++)//这里的n代表是n皇后问题,如果是8皇后,n为8
{
attack.push_back(vector<int>());//这里是先插入一个占住位置,后面再用循环进行修改
for(int j = 0; j<n;j++)
{
attack[i].push_back(0);
}
queen.push_back("");//插入一个占住位置,然后再进行修改
queen[i].append(n,'.');//第i行插入n个'.'
}
- 第二个要解决的问题是皇后的插入,要专门写一个函数用于插入,然后利用两个数组dx和dy进行方向的变换,同时在插入后,attack的0也更新为1:
//x,y为要插入的皇后的位置,queen为皇后表,attack为皇后攻击表
void put_queen(int x,int y,vector<vector<int>>&attack)
{
//x,y在围绕着皇后棋盘上的变化
static const int xx[] = {-1,1,0,0,-1,-1,1,1};
static const int yy[] = {0,0,-1,1,-1,1,-1,1};
attack[x][y]=1;//皇后位置置为1
for(int i = 0;i<attack.size();i++)//从皇后位置向1到n-1个位置延伸
{
for(int j = 0;j<8;j++)//8种变化方法
{
int dx = x + xx[j]*i;
int dy = y + yy[j]*i;
//当前移动的位置还在棋盘内
if(dx >= 0 && dx < attack.size() && dy >= 0 && dy < attack.size())
{
attack[dx][dy] = 1;//将当前位置设置成可攻击
}
}
}
}
3.下面第三步就要进行回溯了
//回溯法求解N皇后的递归函数
/*
k表示当前处理的行
n表示N皇后问题
queen存储皇后的位置
attack标记皇后的攻击位置
solve存储N皇后的全部解法
*/
void dfs(int k,int n,vector<string>&queen,vector<vector<int>>&attack,vector<vector<string>>&solve)
{
if(k == n)
{
solve.push_back(queen);
return;
}
for(int i = 0;i<n;i++)//这个n代表的是n皇后问题,其实也就是列的循环
{
if(attack[k][i] = 0)
{
vector<vector<int>>temp = attack;
queen[k][i] = 'Q';
put_queue(k,i,attack);
dfs(k+1,n,queen,attack,solve);
attack = temp;
queen[k][i] = '.';
}
}
}
完整代码:
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>>solve;
vector<vector<int>>attack;
vector<string>queen;
//矩阵初始化
for(int i = 0;i<n;i++)
{
attack.push_back(vector<int>());//随便添加一个行
for(int j = 0;j<n;j++)
{
attack[i].push_back(0);//将每一行全部置为0
}
queen.push_back("");//随便添加一行
queen[i].append(n,'.');//将这一行全部置为.
}
//回溯求解n皇后
backtrack(0,n,queen,attack,solve);
return solve;
}
private:
//实现在(x,y)防止函数,二维数组attack表示棋盘是否可放置皇后
void put_queen(int x,int y,vector<vector<int>>&attack)
{
static const int dx[] = {-1,1,0,0,-1,-1,1,1};
static const int dy[] = {0,0,-1,1,-1,1,-1,1};
attack[x][y] = 1;
for(int i = 0;i<attack.size();i++)//从皇后位置向1到n-1个位置延伸
for(int j = 0;j<8;j++)//遍历八个方向
{
int nx = x + i*dx[j];
int ny = y + i*dy[j];
if(nx >= 0 && nx < attack.size() && ny >= 0 && ny <attack.size())//在棋盘范围内
attack[nx][ny] = 1;
}
}
//回溯法求解N皇后的递归函数
/*
k表示当前处理的行
n表示N皇后问题
queen存储皇后的位置
attack标记皇后的攻击位置
solve存储N皇后的全部解法
*/
void backtrack(int k,int n,vector<string>&queen,vector<vector<int>>&attack,vector<vector<string>>&solve)
{
if(k == n)//找到一组解法
{
solve.push_back(queen);
return;
}
for(int i = 0;i<n;i++)//这个n代表的是n皇后问题
{
if(attack[k][i] == 0)
{
vector<vector<int>>temp = attack;
queen[k][i] = 'Q';
put_queen(k,i,attack);
backtrack(k+1,n,queen,attack,solve);
attack = temp;
queen[k][i] = '.';
}
}
}
};