蓝桥杯 基础练习 2n皇后问题

蓝桥杯 基础练习 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却是对的)
刚开始写博客,有问题请指教

发布了8 篇原创文章 · 获赞 0 · 访问量 709

猜你喜欢

转载自blog.csdn.net/Daturasee/article/details/104784543