力扣第52题,N皇后II,dfs+回溯剪枝
- N皇后 II
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
示例:
输入: 4 输出: 2 解释: 4 皇后问题存在如下两个不同的解法。 [ [".Q…", // 解法 1 “…Q”, “Q…”, “…Q.”],
["…Q.", // 解法 2 “Q…”, “…Q”, “.Q…”] ]
题意: N*N的棋盘上,放n个皇后,使每个皇后在不同行,不同列,不在同一条对角线上 思路: dfs+回溯 我们可以按照一行一行的来选择不同的列,设置visited[]来判断哪些列已经被选了. path数组,存储已经选择的列,下标就是行,值就是列. dfs函数 参数 n 是已经选择了多少行,visited是用来挑选哪些列可以被选择. path数组用来存储一个方案的结果 首先先判断 n是否等于N,表示是否已经选择完了,如果选择完了,计数器cnt++ 如果没有,枚举每一列继续选择某一列未被选择且不和前面已经选择的发生冲突. if(!visited[i])未被访问的 判断是否与之前的选择的列是否发生冲突,由于我的选择是每一行,然后不同列,故只需要判断是否在对角线上,判断是否在对角线上,例如两个点(x1,y1) (x2,y2) 就是判断横坐标之差的绝对值和纵坐标之间的绝对值是否相同 这个就是回溯剪枝的操作
bool flag = true; for (int j = 0; j < n; j++){ //判断是否与之前的点发生冲突 if (abs(path[j] - i) == n - j){ flag = false; break; } }
满足条件,就是寻找下一行的某一列,继续dfs. dfs结束后,还原这一行的情况,visit[i]标志为未访问,path中删除这一行
#include<iostream> #include<vector> #include<cmath> using namespace std; class Solution { public: int cnt; int N; int totalNQueens(int n) { N = n; cnt = 0; vector<bool> visited(n, false); vector<int> path; dfs(visited, 0, path); return cnt; } void dfs(vector<bool> &visited, int n, vector<int>&path) { if (n == N) { cnt++; return; } for (int i = 0; i < N; i++) { //寻找未被占用的列,并且不和之前的点冲突的列 if (!visited[i]){ bool flag = true; for (int j = 0; j < n; j++){ //判断是否与之前的点发生冲突 if (abs(path[j] - i) == n - j){ flag = false; break; } } if (flag) { visited[i] = true; path.push_back(i); dfs(visited, n + 1, path); path.pop_back(); visited[i] = false; } } } } }; int main() { Solution s; cout<<s.totalNQueens(5); }
下一篇:
线程二十一—— 加锁