题目描述
思路
回溯法, 直接上代码
#include <iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
/********************更新标记数组**********************/
void put_down_the_queen(int x, int y, vector<vector<int>>& mark) {
static const vector<int> vecx = { 0, 0, -1, 1, -1, 1, -1, 1 };
static const vector<int> vecy = { -1, 1, 0, 0, -1, -1, 1, 1 };
mark[x][y] = 1; //x,y放置皇后后进行标志
for (int i = 1; i < mark.size(); i++) { //最多扩展N - 1次
for (int j = 0; j < 8; j++) { //每次扩展8个方向
int new_x = x + i * vecx[j];
int new_y = y + i * vecy[j];
if (new_x >= 0 && new_x < mark.size() && new_y >= 0 && new_y < mark.size()) //如果在棋盘内
mark[new_x][new_y] = 1;
}
}
}
/********* 参数**********
正在放置第k个皇后(放在第k行), 将某次放好的结果存放在location中, 最终结果存放在result中, 棋盘的标记数组mark
*************************/
void Solve(int k, int N, vector<string>& location, vector<vector<string>>& result, vector<vector<int>>& mark) {
if (k == N) {
result.push_back(location); //当k == n 时,表示完成了第 0 到 n - 1 行的放置
return;
}
for (int i = 0; i < N; i++) { //第k行,第i列
if (mark[k][i] == 0) { //如果第k行第i列未被标记,则可以放置皇后并进行标记
vector<vector<int>> temp_mark = mark; //设置回溯前标记的镜像
location[k][i] = 'Q'; //放置皇后
put_down_the_queen(k, i, mark); //对放置皇后后的横竖斜方向进行标记
Solve(k + 1, N, location, result, mark); //递归的进行下一行第k + 1个皇后的放置
mark = temp_mark; //将mark重新恢复为回溯前的状态
location[k][i] = '.'; //将当前的皇后位置重置回'.'
}
}
}
vector<vector<string>> solve_N_queen(int N) {
vector<vector<string>> result; //最终的结果
vector<vector<int>> mark(N, vector<int>(N, 0)); //初始化二维vector,为N*N的vector,所有值为0.
vector<string> location(N); //存储某次摆放结果
for (int i = 0; i < N; i++) { //初始化摆放结果全为 '.'(未放置的情况)
location[i].append(N, '.');
}
Solve(0, N, location, result, mark);
return result;
}
int main() {
vector<vector<string>> res = solve_N_queen(8);
for (int i = 0; i < res.size(); i++) {
cout << "i = " << i << endl;
for (int j = 0; j < res[i].size(); j++) {
cout << res[i][j] << endl;
}
cout << endl;
}
}
输出示例: