最近开始打卡LeetCode每日一题,也在此记录一下解题思路。
题目介绍
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一或 N-1 步,可进可退。【引用自百度百科-皇后】
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。即在相同行、列、斜线上都只能有一个皇后。需要求出一共有多少种放置的方法,分别是什么样的。
解题思路
这个算法需要使用到回溯的思想,遍历每一行的每一列寻找该行能够放置棋子的位置。如果一整行都不存在可以放置的位置,则需要回溯到上一行,从上一行的下一列开始重新寻找解决方法。
下面给出一个算法思路:
- 清空棋盘,从棋盘的第一行 i 、第一列 j 开始;
- 若该位置可以放置棋子,则记录该位置,则跳转至第5步;否则,进入第3步;
- 当前位置不能放置:
1)如果当前列不是最后一列,则当前列改为后一列,回到第2步;
2)当前列为最后一列(或已超出),则该行没有可以放置皇后的位置,需要回溯上一行,进入下第4步; - 如果当前行是第一行,说明已经找完所有,退出;否则,记当前行为上一行,记当前列为当前行记录位置的下一列,清空当前行的标记,回到第2步;
- 在成功放置一个棋子后:
1)如果当前行是最后一行,则说明找到一种解法; 记当前列为下一列,清空当前行的标记,回到第2步;
2)如果当前行不是最后一行,则记当前行为下一行,当前列回到第一列,回到第2步。
记录棋盘中棋子的存放位置最容易想到的便是使用二维数组,但其实可以使用一个长度为n的一维数组Arr[n]
来进行存储。第 i 行第 j 列放置一个皇后便可以表示为Arr[i] = j
,每个元素代表一行。
在计算冲突时:
对于图中5*5棋盘A所示的皇后的位置,其攻击范围为有颜色的区域。因为我们探索的顺序是从第一行开始,所以放置A时下面的区域是还没有放置棋子的,可以不用考虑。按行探索,所以同一行也不会存在冲突。则只需要判断上方蓝色区域是否存在冲突。
对于同一列,只需判断是否值相同;而在同一条斜线上的两个位置,其行号差与列号差的绝对值是相同的。
代码
class Solution {
public:
int totalNQueens(int n) {
dim =