(蓝桥杯)从八皇后问题到2n皇后问题

引入:为了点击量丧心病狂地添加了蓝桥杯三个字,虽然并没有什么用

1. 八皇后问题

以国际象棋为背景:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

使用回溯和递归的方法进行的求解

#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <cmath>

using namespace std;

int a[10][10];
// 摆在每行的哪一列
int thehang[10];
// 哪一列是否已有了
int ishas[10];
// 有多少组
int flag = 0;

void put(int hang, int lei)
{
	if (thehang[8] != 0)
	{
		for (int i = 1; i <= 8; i++)
		{
			printf_s("%d",thehang[i]);
		}
		cout << endl;
		flag++;
		return;
	}
	if (hang > 8 || lei > 8)
		return;

	// 第一行
	if (hang == 1)
	{
		a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
		// 从下一行第一列开始找
		put(hang + 1, 1);
		// 回溯,即返回到原来的样子
		a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
	}
	// 非第一行
	else {
		// 做下一行处理
		int temp;
		for (temp = 1; temp < hang; temp++)
		{
			// 是否同列有,对角线有(每行比)
			if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei)
			{
				put(hang, lei + 1);
				return;
			}
		}
		if(temp==hang)
		{
			a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
			put(hang + 1, 1);
			a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
		}
	}

	if (lei < 8)
		put(hang, lei + 1);
}

int main()
{
	memset(a, 0, sizeof(a));
	memset(ishas, 0, sizeof(ishas));
	put(1, 1);
	printf_s("%d", flag);
}

2. n皇后问题

棋盘的大小变为n×n,而皇后个数也变成n。(0<n<=10)

递归函数里增加一个参数表示n,用n来代替8,会了八皇后直接改参数就可以了
真是个小天才

#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <cmath>

using namespace std;

int a[10][10];
// 摆在每行的哪一列
int thehang[10];
// 哪一列是否已有了
int ishas[10];
// 有多少组
int flag = 0;

void put(int hang, int lei, int size)
{
	if (thehang[size] != 0)
	{
		for (int i = 1; i <= size; i++)
		{
			printf_s("%d",thehang[i]);
		}
		cout << endl;
		flag++;
		return;
	}
	if (hang > size || lei > size)
		return;

	// 第一行
	if (hang == 1)
	{
		a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
		// 从下一行第一列开始找
		put(hang + 1, 1, size);
		// 回溯,即返回到原来的样子
		a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
	}
	// 非第一行
	else {
		// 做下一行处理
		int temp;
		for (temp = 1; temp < hang; temp++)
		{
			// 是否同列有,对角线有(每行比)
			if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei)
			{
				put(hang, lei + 1, size);
				return;
			}
		}
		if(temp==hang)
		{
			a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
			put(hang + 1, 1, size);
			a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
		}
	}

	if (lei < size)
		put(hang, lei + 1, size);
}

int main()
{
	int n;
	cin >> n;
	memset(a, 0, sizeof(a));
	memset(ishas, 0, sizeof(ishas));
	put(1, 1, n);
	printf_s("%d", flag);
}

3. 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

方法基本一致,细节以后再来解释
毕竟调试地要吐了

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <cmath>

using namespace std;

int a[10][10];

// 白摆在每行的哪一列
int thehang[10];
// 白哪一列是否已有了
int ishas[10];

// 黑摆在每行的哪一列
int black_thehang[10];
// 黑哪一列是否已有了
int black_ishas[10];

// 有多少组
int flag = 0;

// 放黑皇后(0:不能放; 1:可以放; 2:放过白的了; 3:放过黑的了)
void put_black(int hang, int lei, int size)
{
	// 达成一次2n问题
	if (black_thehang[size] != 0)
	{
		flag++;
		return;
	}

	if (hang > size || lei > size)
		return;

	// 第一行
	if (hang == 1)
	{
		if (a[hang][lei] == 1)
		{
			a[hang][lei] = 3; black_ishas[lei] = 1; black_thehang[hang] = lei;
			// 从下一行第一列开始找
			put_black(hang + 1, 1, size);
			// 回溯,即返回到原来的样子
			a[hang][lei] = 1; black_ishas[lei] = 0; black_thehang[hang] = 0;
		}
	}
	// 非第一行
	else {
		// 做下一行处理
		int temp;
		for (temp = 1; temp < hang; temp++)
		{
			// 是否同列有,对角线有(每行比)
			if (hang - temp == abs(black_thehang[temp] - lei) || black_thehang[temp] == lei || a[hang][lei] != 1)
			{
				put_black(hang, lei + 1, size);
				return;
			}
		}
		if (temp == hang)
		{
			a[hang][lei] = 3; black_ishas[lei] = 1; black_thehang[hang] = lei;
			put_black(hang + 1, 1, size);
			a[hang][lei] = 1; black_ishas[lei] = 0; black_thehang[hang] = 0;
		}
	}

	if (lei < size)
		put_black(hang, lei + 1, size);
}

// 放白皇后(0:不能放; 1:可以放; 2:放过白的了)
void put(int hang, int lei, int size)
{
	if (thehang[size] != 0)
	{
		// 白的已经放好了
		put_black(1, 1, size);
		return;
	}
	if (hang > size || lei > size)
		return;

	// 第一行
	if (hang == 1)
	{
		if (a[hang][lei] == 1)
		{
			a[hang][lei] = 2; ishas[lei] = 1; thehang[hang] = lei;
			// 从下一行第一列开始找
			put(hang + 1, 1, size);
			// 回溯,即返回到原来的样子
			a[hang][lei] = 1; ishas[lei] = 0; thehang[hang] = 0;
		}
	}
	// 非第一行
	else {
		// 做下一行处理
		int temp;
		for (temp = 1; temp < hang; temp++)
		{
			// 是否同列有,对角线有(每行比)
			if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei || a[hang][lei] == 0)
			{
				put(hang, lei + 1, size);
				return;
			}
		}
		if(temp==hang)
		{
			a[hang][lei] = 2; ishas[lei] = 1; thehang[hang] = lei;
			put(hang + 1, 1, size);
			a[hang][lei] = 1; ishas[lei] = 0; thehang[hang] = 0;
		}
	}

	if (lei < size)
		put(hang, lei + 1, size);
}

int main()
{
	int n;
	cin >> n;
	memset(a, 0, sizeof(a));
	memset(ishas, 0, sizeof(ishas));
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
			scanf("%d", &a[i][j]);
	}
	put(1, 1, n);
	printf("%d", flag);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值