蓝桥杯 基础练习 2n皇后问题C/C++
借鉴了一下其他的代码后完成。
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
注意:
1.对角线指该点的左右对角线,非整个矩阵的对角线
2.下边的点还没放故只需判断:该点是否为1、所选列、该点左上对角线、右上对角线是否同类型皇后。
3.dfs下一个点后,该点返回vis[x][i]=1的状态。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int n;
int vis[10][10];
int cnt=0;
void P()//调试时的打印函数,可删去
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<vis[i][j]<<" ";
}
cout<<endl;
}
cout<<"*****************"<<endl;
}
//判断(x,y)的列,左上对角线、右上对角线是否有同类型皇后
int check(int x,int y,int k)
{
int x1=x,y1=y;
for(int i=1;i<=n;i++)
if(vis[i][y]==k)//列
return 0;
while((--x1)>0&&(--y1)>0)//左上
{
if(vis[x1][y1]==k)
return 0;
}
while((x--)>0&&(y++)<=n)//右上
{
if(vis[x][y]==k)
return 0;
}
return 1;
}
void dfs_w(int x)//白皇后
{
if(x==n+1)//终止条件
{
//P();
cnt++;
return;
}
for(int i=1;i<=n;i++)
{
if(vis[x][i]==1&&check(x,i,3))
{
vis[x][i]=3;
dfs_w(x+1);
vis[x][i]=1;
}
}
}
void dfs_b(int x)//黑皇后
{
if(x==n+1)
{
// P();
dfs_w(1);
return;
}
for(int i=1;i<=n;i++)
{
if(vis[x][i]==1&&check(x,i,2))
{
vis[x][i]=2;
dfs_b(x+1);
vis[x][i]=1;
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>vis[i][j];//0对应的位置不能放
}
}
dfs_b(1);
cout<<cnt;
return 0;
}