基础练习 2n皇后问题
时间限制: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
思路:
先要知道n皇后问题的解决思路:N皇后问题传送门
2n皇后问题的解决思路是先放置好所有的黑皇后,然后再放置白皇后
特别要注意/放置白皇后的时候需要注意当前块上是否可以放置白皇后(即map[][]不为0),以及是否有黑皇后 (q[i][0]!=k)
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
int map[10][10],ans,n;
int q[10][2]; //存储黑皇后和白皇后所在的列
//思路是先放置好所有的黑皇后然后再放置白皇后
//放置白皇后的时候需要注意当前块上是否可以放置白皇后,以及是否有黑皇后
bool find(int i,int k,int t)
{
int j=1;
while(j<i)
{
if(q[j][t]==k ||abs(j-i)==abs(q[j][t]-k))
return false;
j++;
}
return true;
}
void dfs(int i,bool flag) //设置标记true表示当前放置的是黑皇后
{
if(i>n && flag) //黑皇后已经放置完
dfs(1,false);
if(i>n && !flag) //全部放置完毕
ans++;
if(i<=n && flag)
{
for(int k=1;k<=n;k++)
{
if(find(i,k,0) && map[i][k]) //还要考虑该块是1
{
q[i][0]=k;
dfs(i+1,true);
}
}
}
else
{
for(int k=1;k<=n;k++)
{
if(find(i,k,1) && q[i][0]!=k && map[i][k]) //还要注意该块中无黑皇后
{
q[i][1]=k;
dfs(i+1,false);
}
}
}
}
int main()
{
int i,j,res[10];
//打表
/* for(i=0;i<=8;i++)
{
ans=0;
dfs(i);
res[i]=ans;
}*/
while(~scanf("%d",&n))
{
ans=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
}
}
dfs(1,true); //从第一行开始放置
printf("%d\n",ans);
}
return 0;
}