LeetCode 51. N 皇后

本文介绍了如何使用回溯法解决N皇后问题,给出了C++代码实现,包括put_queen函数用于标记皇后位置及其攻击范围,以及backtrack函数进行递归求解。示例展示了4皇后问题的两种解法,并提供了主函数main来展示结果。
摘要由CSDN通过智能技术生成

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例 1:
在这里插入图片描述输入:n = 4
输出:[[".Q…","…Q",“Q…”,"…Q."],["…Q.",“Q…”,"…Q",".Q…"]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:[[“Q”]]
提示
1 <= n <= 9
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

大佬思路1:详情见下

#include <iostream>
#include <vector>
using namespace std;

//自定义函数put_queen,实现在(x,y)放置皇后,对attack数组的更新
//x,y表示放置皇后的坐标,二维数组attack表示棋盘是否可放置皇后
void put_queen(int x, int y, vector<vector<int>>&attack)
{
	//方向数组,方便后面对8个方向进行标记
	static const int dx[] = { -1,1,0,0,-1,-1,1,1 };
	static const int dy[] = { 0,0,-1,1,-1,1,-1,1 };
	attack[x][y] = 1;//将皇后位置标记位1

	//通过两层循环,将皇后可能攻击到的位置进行标记
	for (int i = 1; i < attack.size(); i++)//从皇后位置向1到n-1个距离延伸
	{
		for (int j = 0; j < 8; j++)//遍历8个方向
		{
			int nx = x + i * dx[j];//生成新位置的行
			int ny = y + i * dy[j];//生成新位置的列

			if (nx>=0 && nx<attack.size() && ny>=0 && ny<attack.size())
			{
				attack[nx][ny] = 1;
			}
		}
	}
}

//回溯法求解N皇后的递归函数
//k表示当前处理的行
//n表示N皇后问题
//queen存储皇后的位置
//attack标记皇后的攻击位置
//solve存储N皇后的全部解法
void backtrack(int k, int n, vector<string>&queen, vector<vector<int>>&attack, vector<vector<string>>&solve)
{
	if (k==n)//到了最后一行,找到一组解
	{
		solve.push_back(queen);//将结果queen存储至solve
		return;
	}

	//遍历0至n-1列,在循环中,回溯试探皇后可知放置的位置
	for (int i = 0; i < n; i++)
	{
		if (attack[k][i]==0)//判断当前第k行第i列是否可以放置皇后
		{
			vector<vector<int>>tmp = attack;//备份attack数组
			queen[k][i] = 'Q';//标记该位置位Q
			put_queen(k, i, attack);//更新attack数组
			backtrack(k + 1, n, queen, attack, solve);//递归试探k+1行的皇后放置
			attack = tmp;//恢复attack数组
			queen[k][i] = '.';
		}
	}
}

vector<vector<string>>solveNQueens(int n)
{
	vector<vector<string>>solve;//存储最后结果
	vector<vector<int>>attack;//标记皇后的攻击位置
	vector<string>queen;//保存皇后的位置

	//使用循环初始化attack数组和queen数组
	for (int i = 0; i < n; i++)
	{
		attack.push_back((std::vector<int>()));
		for (int j = 0; j < n; j++)
		{
			attack[i].push_back(0);
		}
		queen.push_back("");
		queen[i].append(n, '.');
	}
	backtrack(0, n, queen, attack, solve);//调用backtrack求解N皇后问题
	return solve;//返回结果数组solve
}
int main()
{	
	vector<vector<string>>result;//设置二维字符串数组存储结果
	result = solveNQueens(5);
	printf("8皇后共有%d种解法:\n\n", result.size());
	//cout << "8皇后共有"<<result.size()<<"种解法" << endl;
	for (int i = 0; i < result.size(); i++)
	{
		printf("解法%d\n", i + 1);
		//cout << "解法" << i + 1;
		for (int j = 0; j < result[i].size(); j++)
		{
			printf("%s\n", result[i][j].c_str());
			//cout << result[i][j].c_str();
		}
		cout << endl;
	}
	return 0;
}


  1. https://www.bilibili.com/video/BV1HZ4y1A7uV ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值