资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
给定一个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
代码
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
//思路: 先对黑皇后进行安放,并记录下所有可能的方法(用二维数组存)
//对于每种已经能放好的黑皇后方法,将黑皇后的位置设为0表示能不能放,
//再去看白皇后有多少种安方法,最后加起来即可
//并且搜黑皇后和搜白皇后其实可以用同一个函数(稍微有些区别,也可以分开更清晰)
int n=0;
int time=0;
int map[10][10]={
0};
int temp[10][10]={
0}; //临时地图
int t=0; //用于记录存放了多少种安置和黑皇的方法
int cun[1000][9]={
0}; //cun[i][j]中,i代表第i种黑皇后放置方法(i从0开始),j代表第j行,cun[1000][8]代表第i种方法中第j行第cun[1000][8]列(存放黑皇)
int queenpos[10]={
0};
int pos[10]={
0};
void queen(int k);
void Bqueen(int k);
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>map[i][j];
}
}
//先对黑皇位置搜索
queen(1); //第1行开始
if(t==0){
cout<<"0";
return 0;
}
int sum=0;
for(int i=0;i<t;i++){
time=0;
memcpy(temp,map,sizeof(map)); //把map值赋值给temp
for(int m=1;m<=n;m++){
temp[m][cun[i][m]]=0; //表示这个位置被黑占用了
}
Bqueen(1); //白皇后开始搜索
sum+=time;
}
cout<<sum;
return 0;
}
void queen(int k){
if(k==n+1){
//表示前k行都已经安放好了皇后
for(int i=1;i<=n;i++){
cun[t][i]=queenpos[i];
}
t++;
return;
}
for(int i=1;i<=n;i++){
//现在处于第k行,对于i列位置进行选择
int j=1;
for(j=1;j<k;j++){
if(queenpos[j]==i||abs(queenpos[j]-i)==abs(k-j)){
break; //表示存在冲突
}
}
if(k==j&&map[k][i]==1){
queenpos[k]=i;
queen(k+1);
}
}
}
void Bqueen(int k){
if(k==n+1){
//表示前k行都已经安放好了皇后
time++;
return ;
}
for(int i=1;i<=n;i++){
//现在处于第k行,对于i列位置进行选择
int j=1;
for(j=1;j<k;j++){
if(pos[j]==i||abs(pos[j]-i)==abs(k-j)){
break; //表示存在冲突
}
}
if(k==j&&temp[k][i]==1){
pos[k]=i;
Bqueen(k+1);
}
}
}