C++蓝桥杯 基础练习 2n皇后问题 HERODING的蓝桥杯之路

资源限制
时间限制: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
样例输出
0

解题思路:
说实话,刚看到这一题我是百思不得其解的,首先我对国际象棋一概不知(后来才知跟这个没关系),其次在我主观臆断里面,n个棋子在n * n的矩阵中怎么可能都满足不同行、不同列、不在同一个对角线上呀,于是乎我大言不惭(不知羞耻)的开始面向百度编程,通过一个老哥的解释我顿时茅塞顿开,悔不当初┭┮﹏┭┮。
言归正传,开始讲解思路。代码段落分为判断函数段(包括黑白),放置函数段(包括黑白),main函数。过程为:先放置黑棋子,利用深度优先和for循环,差不多整个棋盘都访问了一遍,每放置一次要进行条件判断,如果判断成功则可以继续递归调用,否则这路方案不行gg。接着黑棋子布局完毕,开始布置白棋子,道理和黑棋子一致。最后输出成功的次数。

#include<bits/stdc++.h>

using namespace std;

const int maxn = 10;  
int n;  
int map_Q[maxn][maxn];  
int posb[maxn]={0};  //黑皇后 
int posw[maxn]={0};  //白皇后 
int ans;   
 
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
    {  
        ans++;  
      }
    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];    
   ans = 0;  
   dfs_black(1);    //先把黑皇后放在第一列
   cout << ans << endl; 
   
    return 0;  
}

感谢这位老哥的讲解,代码和这位老哥的差不多,添加了一些注释,更方便理解,附上他的链接: link.

发布了7 篇原创文章 · 获赞 8 · 访问量 805

猜你喜欢

转载自blog.csdn.net/HERODING23/article/details/105650555