蓝桥杯 试题 基础练习 2n皇后问题(包含n皇后问题讲解)

时间:2022-07-24
本文章向大家介绍蓝桥杯 试题 基础练习 2n皇后问题(包含n皇后问题讲解),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在动手解决2n皇后问题时我们首先先来解决n皇后问题,所谓皇后问题,想必大家都不陌生,就是采用回溯法来实现

思路:以前以为很难的题,现在动手发现也不是很难,思路其实很简单,我们其实可以直接采用一个一维数组,来表示棋盘,因为棋盘上一行只能有一个皇后,所以的话,我们这样子表示的话,直接能表示出每一个皇后在第几行第几列,然后我们就一行行来找,第一行放在第几个,第二行放在第几个…,如此直到找到每一行都有一个皇后的解,然后tot++;然后返回,这一行继续往下找,看看是否还有满足的解,主要的是一个判断函数,就是在这一行之前看看是否有皇后与之同列或者对角线即可。

#include<bits/stdc++.h>
#define N 10 
using namespace std;

int n;//输入n皇后 
int ans[N];
//bool vis[N];
int tot = 0;//用于统计解的个数 

bool check(int ans[],int x,int y){
	bool flag = 0;
	int res; 
	for(int i=1;i<=x-1 && !flag;i++){
		res = ans[i];
		if(res == y || abs(x - i) == abs(y - res))
		   flag = 1;
	}
	return !flag;
}

void dfs(int m){
       if(m == n+1){
       	tot++;
       	return ;
	   }
	   for(int j=1;j<=n;j++){
	   	   if(check(ans,m,j)){//如果不冲突 
	   	     ans[m] = j;
	   	     dfs(m+1);
			}
	   }
	   return ;	
}

int main(){

	cin>>n;
	dfs(1);//从第一行开始
	cout<<tot<<endl;
	return 0; 
} 

那么我们再来看这个2n皇后问题。

思路:在充分理解n皇后问题的基础上,我们对这个题进行分析,本题多了限制条件,有的位置能放皇后,有的位置不能放皇后。思路详细见代码

#include<bits/stdc++.h> 
#define N 10 
using namespace std; 

  
int n;
  
int map_Q[N][N];
  
int posb[N]={0};  
int posw[N]={0}; 
 
int tot = 0;   
 
bool checkw( int cur) //检查函数
{  
    for( int i = 1; i < cur; i++)  
        if( posw[i] == posw[cur] || abs(i-cur) == abs(posw[i]-posw[cur]))  
            return false;  
    return true;  
}   
 
bool checkb( int cur)  //检查函数
{  
    for( int i = 1; i < cur; i++)  
        if( posb[i] == posb[cur] || abs(i-cur) == abs(posb[i]-posb[cur]))  
            return false;  
    return true;  
}  
 
void dfs_white( int cur)  
{  
    if( cur == n+1)  //白皇后也全部放完,次数+1
    {  
        tot++;  
      }
    for( int i = 1; i <= n; i++)  
    {  
        if( posb[cur] == i) //表示第cur列的第i行位置已经被黑皇后占用,
            continue;        //结束当前循环,i+1
        if( map_Q[cur][i] == 0)  //再判断前提条件是否成立
            continue;  
        posw[cur] = i;    //尝试把第cur列的白皇后放在第i行上
        if( checkw(cur))   //判断能否放置白皇后
            dfs_white(cur+1);  //递归
    }  
}  
  
void dfs_black( int cur)  
{  
    if( cur == n+1)  //当黑皇后处理完时,再处理白皇后
    {  
        dfs_white(1);  
    }  
    for( int i = 1; i <= n; i++)  
    {  
       if( map_Q[cur][i] == 0)  //如果第cur列第i行满足放皇后的前提条件即 mp[cur][i] == 1
            continue;  //如果不满足,则结束当前循环,进行下一次循环即i+1。
         posb[cur] = i;     //就尝试把第cur列的黑皇后放在第i行上
        if( checkb(cur))   //然后判断该尝试是否成立,如成立,则进行递归,如不成立,则尝试把当前列的黑皇后放在下一行(i+1行)上。
            dfs_black(cur+1);  //递归
    }  
}  
  
int main(){     
   cin>>n;
   for( int i = 1; i <= n; i++)   //定义棋盘
       for( int j = 1; j <= n; j++)  
           cin>>map_Q[i][j];    

   dfs_black(1);    //先把黑皇后放在第一列
   cout<<tot<<endl; 
   
   return 0;  
}