题目描述
给定一个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
思路
和经典8皇后没啥区别,缕清思路就好
先放白黑都一样
先放白,放的时候只需检查有没有行列对角线冲突以及该格子是不是1就好;
黑要等白都放完再放
放黑的时候,放的时候需检查有没有行列对角线冲突以及该格子是不是1,以及该列有没有放白
缕清思路…
#include<iostream>
#include<cmath>
using namespace std;
int mp[8][8];//地图信息
int whiteLoc[8],blackLoc[8];//表示在该行中皇后放到了哪一列
int n,ans;
bool check_w(int x,int y)//检查白皇后
{
for(int i=0;i<x;i++)
if(y==whiteLoc[i]||abs(x-i)==abs(y-whiteLoc[i]))//如果该列已经有皇后或者对角线上有
return false;
return true;
}
bool check_b(int x,int y)//检查黑皇后
{
for(int i=0;i<x;i++)
if(y==blackLoc[i]||abs(x-i)==abs(y-blackLoc[i]))
return false;
return true;
}
void blackQueen(int cur)
{
if(cur==n)
ans++;
else
{
for(int j=0;j<n;j++)
{
if(mp[cur][j]==0||whiteLoc[cur]==j)//后放的既要考虑该点能不能放皇后,也要考虑这个顶有没有放相反颜色的皇后
continue;
else if(check_b(cur,j))
{
blackLoc[cur]=j;
blackQueen(cur+1);
}
}
}
}
void whiteQueen(int cur)
{
if(cur==n)//放完白色放黑色
blackQueen(0);
else
{
for(int j=0;j<n;j++)//枚举列
{
if(mp[cur][j]==0)//先放的这个,所以只需考虑能不能放就好了
continue;
else if(check_w(cur,j))//检查冲突
{
whiteLoc[cur]=j;
whiteQueen(cur+1);//走下一列
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&mp[i][j]);
whiteQueen(0);
cout << ans;
}