(原题来自蓝桥杯训练题)给定一个nxn的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?
输入格式:
输入的第一行为一个整数n,1<n<9,表示棋盘的大小。接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式:
输出一个整数,表示总共有多少种放法。
输入样例1:
在这里给出一组输入。例如:
cpp
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
输出样例1:
在这里给出相应的输出。例如:
2
输入样例2:
在这里给出一组输入。例如:
cpp
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
输出样例2:
在这里给出相应的输出。例如:
0
cpp
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int mp[N][N];
bool vy[N],vd[2*N],uvd[2*N];//这里用来给黑皇后做标记,列,正对角线,反对角线
bool vis[N][N];//这里给放过黑皇后的地方做标记,放过了黑皇后以后,白皇后就不能放在这个位置了
bool vy1[N],vd1[2*N],uvd1[2*N];//这里用来给黑皇后做标记,列,正对角线,反对角线
int n;
int ans;//答案
//放入白皇后函数
void dfs_w(int a)
{
if(a==n)
{//白皇后到最后一行的下一行时,答案++;
ans++;
return;
}
for(int i=0;i<n;i++)
{
if(mp[a][i]!=0 && !vy1[i] && !vd1[a+i] && !uvd1[i-a+n] && !vis[a][i]){
vis[a][i]=true;
vy1[i]=vd1[a+i]=uvd1[i-a+n]=1;
dfs_w(a+1);
vy1[i]=vd1[a+i]=uvd1[i-a+n]=0;
vis[a][i]=false;
}
}
}
//放入黑皇后函数
void dfs_b(int x)//x表示第几行
{
if(x==n)
{//黑皇后放完了,那么开始从第一行放白皇后
dfs_w(0);
return;
}
for(int i=0;i<n;i++)//i表示第几列
{
if(mp[x][i]!=0 && !vy[i] && !vd[x+i] && !uvd[i-x+n]){//判断当前位置不能为0,当前列,对角线,反对角线没有被放过
vis[x][i]=true;//给当前位置放入黑皇后
vy[i]=vd[x+i]=uvd[i-x+n]=1;//标记
dfs_b(x+1);
vy[i]=vd[x+i]=uvd[i-x+n]=0;//移除标记
vis[x][i]=false;//移除黑皇后
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>mp[i][j];
}
}
dfs_b(0);
cout<<ans<<endl;
return 0;
}