LeetCode-----第五十一题----- N皇后

N皇后

难度:困难

皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例:

输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

 

提示:

  • 皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到七步,可进可退。(引用自 百度百科 - 皇后 )

题目分析:

       本质上还是回溯法,这里我们先建立一个数组存放0~n-1,其实也就是皇后在每一行的位置。然后进行一个全排列,去判断该全排列是否符合要求即可。因为我们利用一维数组作为存放皇后的位置,所以只要判断斜对角线上是否满足条件即可。

 

参考代码:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <deque>
#include <stack>
#include <algorithm>
#include <map>

using namespace std;

class Solution {
public:
	int my_count = 0;
	vector<string> res;
	vector<vector<string>> result;

	vector<vector<string>> solveNQueens(int n)
	{
		if (n < 1)
			return result;
		int* arr = new int[n];
		for (int i = 0; i < n; i++)
		{
			arr[i] = i;
		}
		str_pl(arr, n, 0);
		return result;
	}

	bool is_q(int* arr, int n)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = i + 1; j < n; j++)
			{
				//i-j或者j-i对应的是高度,arr[i] - arr[j]对应的是宽度,
				//当这个高度和宽度相等时,说明在同一对角线上,是不行的
				if (abs(i - j) == abs(arr[i] - arr[j]))
					return false;
			}
		}
		return true;
	}

	void str_pl(int* arr, int n, int index)
	{
		//结束条件,说明已经排列好了
		if (index == n)
		{
			//先检查这个排列是否符合条件
			if (is_q(arr, n))
			{
				string temp;//建立一个临时字符串用于存放类似于‘Q...’的字符串
				for (int y = 0; y < n; y++)//遍历排列数组,每个位置代表皇后的位置
				{
					for (int x = 0; x < n; x++)//没有到皇后的位置就填‘.’
					{
						if (x == arr[y])
							temp += "Q";
						else
							temp += ".";
					}
					res.push_back(temp);
					temp.clear();
				}
				//把所有的解法存起来
				if (res.size() == n)
				{
					result.push_back(res);
					res.clear();
				}
			}
		}
		else
		{
			for (int p = index; p < n; p++)
			{
				swap(arr[p], arr[index]);
				str_pl(arr, n, index + 1);
				swap(arr[p], arr[index]);
			}
		}
	}
};

int main(void)
{
	Solution my_class;
	my_class.solveNQueens(4);
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值