LeetCode 51.N皇后 & LeetCode 52.N皇后II

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

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

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

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

示例:

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

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

写在前面:

LeetCode有两道题,N皇后和N皇后II,N皇后是把解法一一罗列,而N皇后II是求出N皇后的的解法数目,我这里先从N皇后II求解,再来写N皇后的解答。

其实N皇后问题的解法就是穷举所有情况,只不过是聪明的穷举(即回溯,有些情况下面怎么都无法满足N皇后的规则,就放弃下面的所有解),结合深度优先搜索即可求出所有解。

n皇后问题规则,皇后们不能在同行,同列, 同斜线。

N皇后II:求解的数量

代码:

class Solution {
private:
	vector<int> arr;//用来存储皇后的位置,arr[k]=i代表第k行第i列有一个皇后。
	int count;//用来统计有多少种解法
	int size;//存储N皇后的大小,也就是矩阵的大小,8皇后这个变量值就为8
public:
	bool check(int row, int col)//判断row行col列是否能够放皇后,判断行列斜线是否满足要求
	{
		for (int i = 0; i < row; ++i)//是否跟之前的row行冲突
		{
			//由arr的数组定义可知,每一行放一个皇后,就解决了不在同行的问题
			//下面if判断语句主要判断列和斜线是否满足要求
			//比较斜线, 因为不再同一斜率为1或者-1的斜线。(row - i) / (col - arr[i]) != 1 或 -1,
			//可以取巧用绝对值函数: abs(row - i) != abs(col - arr[i])
			if (col == arr[i] || abs(row - i) == abs(col - arr[i]))
			{
				return false;//不满足条件,直接return false
			}
		}
		return true;
	}
	void solve(int k) {//k为当前打算在第k行放置皇后
		if (k == size)//当k与size相等的时候说明在最后一行已经放好皇后了
		{
			count++;//解法数量加一
			return;
		}
		for (int i = 0; i < size; ++i)//判断第0列到第size-1列是否能放皇后
		{
			if (check(k, i))//检查第k行第i列是否能放置皇后
			{
				arr[k] = i;//如果上面条件判断为true,说明可以在第k行第i列放置皇后,记录数组中
				solve(k + 1);//递归,判断下一行哪些列能放置皇后
			}
		}
	}
	int totalNQueens(int n) {
		size = n;//初始化size,n皇后就有n行n列
		count = 0;//初始计数为0
		arr = vector<int>(n);//初始化数组长度
		solve(0);//从第0行开始判断
		return count;//返回解法数量
	}
};

N皇后:求具体的解

写在前面:

基于上面N皇后II的代码,站在巨人的肩膀上,加以小小的改造,即可求N皇后

代码:

class Solution {
private:
	vector<vector<string>> res;//储存具体的解
	vector<int> arr;
	int count;
	int size;
public:
	bool check(int row, int col)
	{
		for (int i = 0; i < row; ++i)
		{
			if (col == arr[i] || abs(row - i) == abs(col - arr[i]))
			{
				return false;
			}
		}
		return true;
	}
	void solve(int k, vector<string> &v) {//此处使用&v而不直接用v,能节省非常多的内存和时间
		if (k == size)
		{
			res.push_back(v);//把正确的结果集放入res数组中
			count++;
			return;
		}
		for (int i = 0; i < size; ++i)
		{
			string s(size, '.');//比如8皇后就是初始化8个点即“........”
			if (check(k, i))
			{
				arr[k] = i;
				s[i] = 'Q';//将能够放皇后的位置改成‘Q’,比如在第一列放皇后,即“Q.......”
				v.push_back(s);//push当前行的结果入数组
				solve(k + 1, v);
				v.pop_back();//用完之后马上弹出,不影响下一列的判断
			}
		}
	}

	vector<vector<string>> solveNQueens(int n) {
		size = n;
		count = 0;
		arr = vector<int>(n);
		vector<string> v;//最后靠这个v存入每一次满足条件的结果集
		solve(0, v);
		return res;
	}
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值