蓝桥杯 基础练习 2n皇后问题
问题描述
给定一个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皇后问题
接下来介绍该题的主要思路
n皇后和2n皇后问题的主要区别是,在2n皇后问题中,需要记录下其中一个颜色的皇后的摆放位置,摆放完后,再放另一个颜色皇后时绕开已被放置的位置即可。
我使用的是深度优先搜索的方法,先将黑皇后摆放,摆放时记录下位置,将visit [ i ] [ j ] 数组置为1( i , j为横纵坐标 )将黑皇后都摆放完后,开始摆放白皇后,原理相同,只是在摆放的时候保证visit [ i ] [ j ]==0即可。
具体代码如下
代码(C++)
#include<iostream>
#include<cmath>
#define maxsize 8
using namespace std;
int n;
int num=0;//输出结果 符合条件的摆法
int res_b[maxsize]; //符合条件的黑皇后摆放序列
int res_w[maxsize];//符合条件的白皇后摆放序列
int map[maxsize][maxsize];
int visit[maxsize][maxsize];//记录
int dfs_white(int step);
int dfs_black(int step);
bool check_b(int step);
bool check_w(int step);
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
cin>>map[i][j];
visit[i][j]=0;
}
dfs_black(1);
cout<<num;
return 0;
}
int dfs_white(int step)
{
if(step==n+1)//白皇后全部摆放完成
{
num++;
}
for(int i=0;i<n;i++)
{
if(!map[i][step-1]||visit[i][step-1]==1) //是否能存放皇后
continue;
res_w[step-1]=i;
if(check_w(step))
{
visit[i][step-1]=1;
dfs_white(step+1);
visit[i][step-1]=0;
}
}
}
int dfs_black(int step)
{
if(step==n+1)
{
dfs_white(1);//黑皇后全部摆放完成,开始统计白皇后
}
for(int i=0;i<n;i++)
{
if(!map[i][step-1]) //是否能存放皇后
continue;
res_b[step-1]=i;
if(check_b(step))
{
visit[i][step-1]=1;
dfs_black(step+1);
visit[i][step-1]=0;
}
}
}
bool check_b(int step)
{
for(int i=0;i<step-1;i++)
{
if(res_b[i]==res_b[step-1]||abs(step-1-i)==abs(res_b[step-1]-res_b[i])) //保证摆放的位置之前没有出现过 和不在对角线上
return false;
}
return true;
}
bool check_w(int step)
{
for(int i=0;i<step-1;i++)
{
if(res_w[i]==res_w[step-1]||abs(step-1-i)==abs(res_w[step-1]-res_w[i]))//保证摆放的位置之前没有出现过 和不在对角线上
return false;
}
return true;
}
(有一个坑 在蓝桥杯的oj中,第六个点我没有通过 但是我的输出2406却是对的)
刚开始写博客,有问题请指教