LeetCode:N皇后

  在17年的9月份,我写过一个N皇后的博客,当时写的代码是又臭又长又乱,最近闲着,就来做一下LeetCode上中等~困难的题目,看到了N皇后,于是就再次写了一遍,与17年时做法相同,用BFS,这次的代码量以及可读性比以前写的好多了,那么废话不多说了。
    
  
  
  

题目简介:

  n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
  在这里插入图片描述
    上图为 8 皇后问题的一种解法。

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

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

示例:

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

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

  
  

题解:

  这道题说难不难,说简单也不简单,对于不知道如何下手的那些人,难点在于如何去判断彼此之间是否能够相互攻击,即:不同行,不同列,不在一个斜线上
  从规则就可以知道,我们要判断的是某个位置是否在该直线上,也就是简单的数学问题。
  17年的时候,我的想法虽然是这样,但是我的做法是,将下入棋盘的点的坐标保存到一个列表里,每当我新加入一个点,我就会遍历该列表的所有点,判断该点是否与列表中的点在同一条斜线上,这样的做法效率相当低下。
  今天在写的时候,仔细想了以下,其实棋盘上斜线位置其实就是斜率k为k=-1与k=1这两条线,而棋盘上的不同位置则分别是截距不同的直线,那么棋盘大小为n时,就有,k=12*n-1条直线和k=-1,2*n-1条直线,然后建立两个大小为2*n-1数组设其初始值为0表示该斜线上没点,这样当我们新放置一个点进棋盘,我们就能够计算该点处于k=1与k=-1两条直线的什么位置,这里我是用横坐标去计算的,即计算的点为(col,row)与(i,0)
  k为斜率,col为列坐标,row为行坐标(即对应为我们通常理解的col:x,row:y),i为截距,也为我们所建立的两个2*n-1直线数组的索引。
  有:
    k=(col-i)/row=1 =>col-row=i  row>0,col>0
    k=(col-j)/row=-1=>col+row  row>0,col>0
  这样,我们判断一个点所处的位置斜线上是否有点,就判断line1[i]==0&&line2[j]==0,成立则表示没点,不成立则表示有点。

代码:

class SolutionQueen {
public:
	vector<vector<string>> solveNQueens(int n) {
		vector<int>left(2 * n - 1, 0);
		vector<int>right(2 * n - 1, 0);
		vector<vector<string>>res;
		for (int i = 0; i < n; i++) {
			vector<int>col(n, 0);
			int old = res.size();
			op(col, left, right, vector<int>(), res, n, 0, i);
		}
		return res;
	}

	void op(vector<int> c, vector<int>l, vector<int>r, vector<int>colvec, vector<vector<string>>&res, int n, int row, int col) {
		if (c[col] != 0)
			return;
		int left, right;
		if (row == 0) {
			left = col;
			right = n - 1 + col;
		}
		else {
			left = col + row;
			right = col - row + n - 1;
		}
		if (l[left] == 0 && r[right] == 0) {
			c[col] = 1, l[left] = 1, r[right] = 1;
			colvec.push_back(col);
			if (row == n - 1) {
				vector<string> tmp;
				for (int i = 0; i < n; i++) {
					string t(n, '.');
					t[colvec[i]] = 'Q';
					tmp.push_back(t);
				}
				res.push_back(tmp);
				return;
			}
			for (int i = 0; i < n; i++) {
				op(c, l, r, colvec, res, n, row + 1, i);
			}
		}
		else {
			return;
		}
	}
};

  
  虽然这么写,但是效率还是有些低是因为在递归的过程中,拷贝了太多次各种数组,导致效率比其他算法慢,N皇后用dfs写是很快的,bfs则相对要慢很多。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值