n(2n)皇后问题

n皇后问题:

思想:DFS深度遍历。

大体过程是:从网络的每一行开始遍历,首先从第一行开始。在每一行遍历该行所在的列,每一列依次检查,如果当前列满足条件(也就是不重列,不重对角线,这里的行重复这个条件不用管,因为我们每一行只放一个),那么就说明这一行可以放,就可以转入到下一行中了,下一行的操作思想同这一行一样,所以这就是一个递归过程。要注意的是,当成功全部放置完成时,也就是n行全部摆满,这时候就可以将技术方法+1了。另外,DFS当前递归完成时,会进行回退操作,我们就开始尝试当前列的下一列,所以我们要将之前放置的皇后给回收,也就是a[N]置0。

#include<iostream>
#include<cstdlib>
#include<cstdlib>

using namespace std;
const int N = 10;
int n;
int a[N];//a[i]表示第i行上的皇后放于a[i]列上,假设a[3]=7,也就是第三行的皇后放于第七列的单元格上
int cnt;

bool check(int x, int y) {//第x行,能不能把皇后放在y上面
	for (int i = 1; i <= x; i++) {
		if (a[i] == y) return false;
		if (i + a[i] == x + y) return false;
		if (i - a[i] == x - y) return false;
	}
}
void dfs(int row) { //第几行皇后放于何处
	if (row == n + 1) {
		cnt++;//产生了一组这样的解
		return;
	}
	for (int i = 1; i <= n; i++) {
		if (check(row, i)) {
			a[row] = i;
			dfs(row + 1);//如果能放就继续下一行
			a[row] = 0;
		}
	}

}
int main() {
	cin >> n;
	dfs(1);
	cout << cnt;
	return 0;
}

2n皇后问题

2n皇后问题总体看来跟n皇后问题差不多。

具体思路:先放置黑皇后,检查当前皇后能不能放入当前位置(棋盘允许放入吗),如果允许,就将棋子放入,然后进行进一步检查(列不重复,对角线不重复,行因为是我们每行只放一个,所以这个不用判断),如果满足条件,剩下的道理就同n皇后一样了,开始处理下一行,另外这里也要注意在当前列结束进入下一列时,记得回收当前放置的棋子,以及递归结束条件是所有行全部放完,也就是放到了n+1行。到了n+1行表示黑棋子已放完,然后我们接着放白棋子。道理同黑棋子一样,具体细节看注释就ok。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#define N 10 
using namespace std;


int n;

int checkerboard[N][N];

int posb[N];
int posw[N];

int total = 0;

bool checkw(int current_row) //检查函数
{
    for (int i = 1; i < current_row; i++)
        if (posw[i] == posw[current_row] || abs(i - current_row) == abs(posw[i] - posw[current_row]))
            return false;
    return true;
}

bool checkb(int current_row)  //检查函数
{
    for (int i = 1; i < current_row; i++)//行遍历
        if (posb[i] == posb[current_row] || abs(i - current_row) == abs(posb[i] - posb[current_row]))
            return false;
    return true;
}

void dfs_white(int current_row)
{
    if (current_row == n + 1)  //白皇后也全部放完,次数+1
    {
        total++;
    }
    for (int i = 1; i <= n; i++)
    {
        if (posb[current_row] == i) //表示第current_row行的第i列位置已经被黑皇后占用,
            continue;        //结束当前循环,i+1
        if (checkerboard[current_row][i] == 0)  //再判断前提条件是否成立
            continue;
        posw[current_row] = i;    //尝试把第current_row行的白皇后放在第i列上
        if (checkw(current_row))   //判断能否放置白皇后
            dfs_white(current_row + 1);  //递归
        else
            posw[current_row] = 0;
    }
}

void dfs_black(int current_row)//当前第一行
{
    if (current_row == n + 1)  //当黑皇后处理完时,再处理白皇后
    {
        dfs_white(1);
    }
    for (int i = 1; i <= n; i++)//列遍历
    {
        if (checkerboard[current_row][i] == 0)  //如果第current_row行第i列满足放皇后的前提条件即 checkerboard[current_row][i] == 1
            continue;  //如果不满足,则结束当前循环,进行下一次循环即i+1。
        posb[current_row] = i;     //就尝试把第current_row行的黑皇后放在第i列上
        if (checkb(current_row))   //然后判断该尝试是否成立,如成立,则进行递归,如不成立,则尝试把当前列的黑皇后放在下一行(i+1行)上。
            dfs_black(current_row + 1);  //递归
        posb[current_row] = 0;
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)   //定义棋盘
        for (int j = 1; j <= n; j++)
            cin >> checkerboard[i][j];

    dfs_black(1);    //先摆黑皇后
    cout << total << endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据给定的问题描述和代码,这是一个关于蓝桥杯C++题目中的n皇后问题。题目要求在一个n*n的棋盘上放置n个黑皇后和n个白皇后,使得任意两个黑皇后和任意两个白皇后都不在同一行、同一列或同一条对角线上。代码使用递归和回溯的方法来解决这个问题。 代码中的pd1函数用于判断黑皇后的位置是否合法,pd2函数用于判断白皇后的位置是否合法。fang1函数用于放置黑皇后,fang2函数用于放置白皇后。最后,通过调用fang1函数来计算总共有多少种放法。 需要注意的是,代码中使用的p1和p2数组分别表示黑皇后和白皇后的位置,qi数组表示棋盘上每个位置是否可以放皇后。 因此,根据给定的代码,可以计算出总共有多少种放法。 #### 引用[.reference_title] - *1* [蓝桥杯 基础练习 2n皇后问题C/C++(可作DFS练习)](https://blog.csdn.net/qq_43838669/article/details/129306490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [蓝桥杯2n皇后问题](https://blog.csdn.net/qq_59611494/article/details/128682794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值