N皇后问题。
下面给出一个类,可以解决三个问题:
给定N*N的棋盘,N个皇后。
①得到一个解;
②得到所有解的个数;
③得到所有解。
上述三个问题分别对应类中的函数:
①Return_an_ans;
②Return_all_ans_num;
③Return_all_ans;
注意第一个函数可以返回相当大的解决方案,因为对于第一个问题我们的解决方法是构造法。
class Queen {
public:
char QChar, BChar; // 代表皇后和空白的字符
int * q_in_row; // q_in_row[i] = j表示在第i行第j列有个皇后
bool * col_free; // col_free[i] = true表示第i列没有皇后
bool * up_free; // 从右上到左下的对角线是否可以放置皇后
bool * down_free; // 从左上到右下的对角线是否可以放置皇后
int N; // 皇后个数、正方形棋盘的边长
bool ONE, NUM, ALL; // 由于只有一个递归函数,三个变量用于区分是哪一个问题
bool ONE_FINISH; // 判断只返回一个解的问题是否已经解决
int num; // 所有解的个数
vector<vector<char> > oneAns; // 一个解
vector<vector<vector<char> > > allAns; // 所有解
Queen() {
QChar = 'Q';
BChar = '.';
ONE = NUM = ALL = ONE_FINISH = false;
}
void changeChar(char q, char b) { // 可以改变代表皇后和空白的字符
QChar = q;
BChar = b;
}
void makeBoard(int n) {
N = n;
q_in_row = new int[N];
col_free = new bool[N];
up_free = new bool[2 * N - 1];
down_free = new bool[2 * N - 1];
for (int i = 0; i < N; i++) q_in_row[i] = col_free[i] = true;
for (int i = 0; i < 2 * N - 1; i++) up_free[i] = down_free[i] = true;
}
void deleteBoard() {
delete []q_in_row;
delete []col_free;
delete []up_free;
delete []down_free;
}
void construct_solution() { // 构造法
int row = 0;
if (N % 6 != 2 && N % 6 != 3) {
if (N % 2 == 0) {
for (int i = 2; i <= N; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
} else {
for (int i = 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N; i += 2) q_in_row[row++] = i - 1;
}
} else {
if (N % 2 == 0) {
if ((N / 2) % 2 == 0) {
for (int i = N / 2; i <= N; i += 2) q_in_row[row++] = i - 1;
for (int i = 2; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = N / 2 + 3; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
} else {
for (int i = N / 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = N / 2 + 3; i <= N; i += 2) q_in_row[row++] = i - 1;
for (int i = 2; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
}
} else {
if ((N / 2) % 2 == 0) {
for (int i = N / 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
for (int i = 2; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = N / 2 + 3; i <= N - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
q_in_row[row++] = N - 1;
} else {
for (int i = N / 2; i <= N - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = 1; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
for (int i = N / 2 + 3; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
for (int i = 2; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
q_in_row[row++] = N - 1;
}
}
}
write_in(oneAns);
}
vector<vector<char> > Return_an_ans(int n) {
makeBoard(n);
if (n > 3) {
construct_solution();
deleteBoard();
return oneAns;
}
ONE = true;
dfs(0);
deleteBoard();
return oneAns;
}
int Return_all_ans_num(int n) {
makeBoard(n);
NUM = true;
num = 0;
dfs(0);
deleteBoard();
return num;
}
vector<vector<vector<char> > > Return_all_ans(int n) {
makeBoard(n);
ALL = true;
dfs(0);
deleteBoard();
return allAns;
}
void write_in(vector<vector<char> > & a) {
a.resize(N);
for (int i = 0; i < N; i++) {
a[i].resize(N);
for (int j = 0; j < N; j++) {
if (q_in_row[i] == j) a[i][j] = QChar;
else a[i][j] = BChar;
}
}
}
void dfs(int now) {
if (now == N) {
if (ONE) {
ONE_FINISH = true;
write_in(oneAns);
return;
}
if (NUM) {
num++;
return;
}
if (ALL) {
vector<vector<char> > a;
write_in(a);
allAns.push_back(a);
return;
}
}
for (int col = 0; col < N; col++) {
if (col_free[col] && up_free[now + col] && down_free[now - col + N - 1]) {
q_in_row[now] = col;
col_free[col] = up_free[now + col] = down_free[now - col + N - 1] = false;
dfs(now + 1);
if (ONE && ONE_FINISH) return;
col_free[col] = up_free[now + col] = down_free[now - col + N - 1] = true;
}
}
}
};
附上测试结果: