主要思想是用递归和回溯法,这样可以找到所有结果。
以行为单位,先找黑皇后的位置,再找白皇后的位置,找不到就进行回溯,具体回溯看代码
函数返回的条件是n行皇后全部找完,仍然进行回溯来找其他结果
代码如下:
#include<stdio.h>
#include<math.h>
//从第1行开始,先放黑皇后,更新数组为0,然后再放白皇后
int black[10];
int white[10];
int a[10][10];
int n;
int judge(int cur, int queen[],int k)
{
for (int i = 1; i < cur; i++) {
//行肯定不同,那么就判断列不同和不在对角线上
if (queen[i] == k || cur - i == fabs(k - queen[i])) return 0;
}
return 1;
}
int count = 0;
int row1 = 1, row2 = 1;//row1为黑皇后的行,row2为白皇后的行
void queen()
{
if (row1 > n && row2 > n) {
count++;
//全部找完则回溯,继续找符合的白皇后
row2--;
a[row2][white[row2]] = 1;
white[row2] = 0;
return;
}
for (int i = 1; i <= n; i++) {
if (a[row1][i] != 0 && judge(row1, black,i)){
//找到一个黑皇后的位置
black[row1]=i;
a[row1][i]=0;
row1++;
//现在开始找白皇后
for (int j = 1; j <= n; j++) {
if (a[row2][j] != 0 && judge(row2, white,j)) {
white[row2] = j;
a[row2][j] = 0;
row2++;
//找到白皇后,开始找下一行
queen();
}
}
//这一列全部找完还没有找到一个对应的白皇后,说明row1找到的黑皇后位置不行,那么就要回溯
row1--;
a[row1][black[row1]] = 1;
black[row1] = 0;
}
}
//这一列全部找完还没有找到一个对应的黑皇后,说明上一行的row2找到的白皇后位置不行,要回溯
row2--;
a[row2][white[row2]] = 1;
white[row2] = 0;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &a[i][j]);
}
}
queen();
printf("%d", count);
return 0;
}