递归算法-N皇后

51. N皇后

难度困难
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。
当然,她横、竖、斜都可走一到七步,可进可退。(引用自 百度百科 - 皇后 )
来源: 添加链接描述
代码思路:
这道题是经典的回溯题,开始我们先要考虑一下怎么生成棋盘并且将“皇后”放入其中,我们可以用二维数组来建立起一个棋盘mark,之后将数组中的每个元素设置成为0来代表是空位,之后用1来代表放置的皇后和皇后所能吃子的范围(就是不能再放入新皇后的位置)之后我们用方向数组的方法来将棋盘上不能放皇后的位置改成1,这样棋盘的函数就写好了。
接下来我们再建立一个和棋盘mark类似的数组location来保存皇后的位置,建立方式和棋盘一样,只不过是用字符串的形式,在没有皇后的位置用‘.'来表示,用’Q‘来表示皇后的位置。
最后开始建立递归函数,因为每一行最多只能有一个皇后,那么我们就每次递归一行棋盘来考虑,每一行只要mark位置上是0就可以放皇后,之后每次递归到下一行,在递归之前用一个临时棋盘来保存现在的棋盘用来之后的回溯用,当我们递归到某行的时候发现没有皇后的位置可以放置了,那么我就要回溯了,返回到没有放皇后的时候,之后换成另一个位置来放置皇后的位置,经过这样的递归一直到n行都放置了皇后就可以结束递归了。

#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
class Solution {
public:
	vector<vector<string> >solveNQueens(int n)
	{
		vector<vector<string> >result;
		vector<vector<int> >mark;
		vector<string>location;
		for (int i = 0;i < n;++i)
		{
			mark.push_back((vector<int>()));
			for (int j = 0;j < n;++j)
			{
				mark[i].push_back(0);
			}
			location.push_back("");
			location[i].append(n, '.');
		}
		generate(0, n, location, result, mark);
		return result;
	}
private:
	void put_down_the_queen(int x, int y,//棋盘函数
		vector<vector<int> >& mark)
	{
		static const int dx[] = { -1,1,0,0,-1,-1,1,1 };
		static const int dy[] = { 0,0,-1,1,-1,1,-1,1 };
		mark[x][y] = 1;
		for (int i = 1;i < mark.size();++i)
		{
			for (int j = 0;j < 8;++j)
			{
				int new_x = x + i * dx[j];
				int new_y = y + i * dy[j];
				if (new_x >= 0 && new_x < mark.size()
					&& new_y >= 0 && new_y < mark.size())
					mark[new_x][new_y] = 1;
			}
		}
	}
	void generate(int k, int n, vector<string>& location,//递归函数
		vector<vector<string> >& result, vector<vector<int> >& mark)
	{
		if (k == n)
		{
			result.push_back(location);
			return;
		}
		for (int i = 0;i < n;++i)
		{
			if (mark[k][i] == 0)
			{
				vector<vector<int> >tmp_mark = mark;
				location[k][i] = 'Q';
				put_down_the_queen(k, i, mark);
				generate(k + 1, n, location, result, mark);
				mark = tmp_mark;
				location[k][i] = '.';
			}
		}
	}
};

int main()
{
     //测试案例
	vector<vector<string> >result;
	Solution solve;
	result = solve.solveNQueens(4);
	for (int i = 0;i < result.size();++i)
	{
		cout << "i = " << i<<endl;
		for (int j = 0;j < result[i].size();j++)
		{
			cout << result[i][j].c_str()<<endl;
		}
		cout << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值