版权声明:记笔记~~~ https://blog.csdn.net/weixin_42765557/article/details/87548144
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1样例输出
0
ways:
和8皇后问题基本一致,可以先安排白皇后,白皇后安排好后再安排黑皇后。
AC代码
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int a[9][9],N,ans;
bool book[9][9]; // book[i][j]用来记录第i行第j个位置有没有皇后在
int col[9][2]; // 第 0 列记录白皇后的位置,第 1 列记录黑皇后的位置
bool Judge(int x,int y,int k)
{
for(int i=1;i<x;i++) {
if(col[i][k] == y || abs(i-x) == abs(col[i][k]-y))
return false;
}
return true;
}
void dfs_b(int n)
{
if(n == N+1) {
ans++;
return;
}
for(int i=1;i<=N;i++) {
if(a[n][i] && !book[n][i])
if(Judge(n,i,1)) {
col[n][1] = i;
book[n][i] = true;
dfs_b(n+1);
book[n][i] = false;
}
}
}
void dfs_w(int n)
{
if(n == N+1) {
dfs_b(1);
return;
}
for(int i=1;i<=N;i++) {
if(a[n][i] && !book[n][i])
if(Judge(n,i,0)) {
col[n][0] = i;
book[n][i] = true;
dfs_w(n+1);
book[n][i] = false;
}
}
}
int main()
{
cin >> N;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
cin >> a[i][j];
memset(book,false,sizeof book);
ans = 0;
dfs_w(1);
cout << ans << endl;
}