基础练习 2n皇后问题

时间:2022-04-27 00:00:47
  基础练习 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
样例输出

#include<stdio.h>
#include<string.h>
#include<math.h>
int n,s;
int g[10][10],c[10],b[10];
//数组c为安放黑皇后的数组,b为白皇后。其中下标表示皇后所在行,值为所在列。
void dfs2(int step)
{
int i,j,flag2;
if(step==n+1)//搜索到一种,种数加一
{
s++;
return;//返回到上一层继续寻找下一种安放方法
}
for(i=1;i<=n;i++)
{
if(g[step][i]==0||c[step]==i)//如果不能安放皇后或者已经放了黑皇后,继续尝试下一列
continue;
flag2=1;
b[step]=i;// ,否则假设该位置已安放上白皇后,检查是否与step之前的行放置的皇后冲突
for(j=1;j<step;j++)
{
if(b[step]==b[j]||abs(b[step]-b[j])==step-j)
   {
flag2=0;
b[step]=-1;
   break;//若冲突,跳出内层循环,继续尝试下一列
}
}
if(flag2)//否则搜索下一行
dfs2(step+1);
}
return ;//若该行的所有列都不满足,返回到上一次调用的位置
 } 
//安放黑皇后
 void dfs1(int step) //搜索行
 {
  int i,j,flag1;
  if(step==n+1) //黑皇后安放完毕,寻找白皇后
  {
  dfs2(1);
  return;
}
for(i=1;i<=n;i++)
{
if(g[step][i]==0)//不能安放皇后,继续寻找
continue;
c[step]=i;//设step,i 可以 放置
flag1=1;
for(j=1;j<step;j++)//寻找step之前已经安放好的行,安放step,i后是否满足题意
{
if(c[step]==c[j]||abs(c[step]-c[j])==step-j) // 若不满足题意
{
flag1=0;
c[step]=-1;//归位
break; // 跳出内层循环,尝试下一列
}
}
if(flag1)//若满足题意,安放下一行
dfs1(step+1);

return;
  } 
int main()
{
int i,j;
scanf("%d",&n);
memset(c,-1,sizeof(c));
memset(b,-1,sizeof(b));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&g[i][j]);
s=0;
    dfs1(1);
    printf("%d",s);
    return 0;
}