;52. N皇后 II](https://leetcode-cn.com/problems/n-queens-ii/)
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回 n 皇后问题 不同的解决方案的数量。
示例 1:
输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:1
提示:
1 <= n <= 9
- 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
其实这道题,我一开始是不大想做的,毕竟,毕竟上面写着困难,但是!但是通过率高达80%;而且通过人数所以我就下定决心做一做了;
这种题一看就是递归,更像是搜索;而且是深度搜索(DFS);
但是如何满足以下:
任何两个皇后都不能处于同一条横行、纵行或斜线上
其实大可以设置一个数组,如果在判断之后在这一个点上可以放置皇后,那么将数组中这一点的横竖斜纵都设置为1;
但是这样写比较麻烦(我一开始就是这样写的);
那么我们大可以找一找规律:
只要这一行有一个皇后,那么这一行就不能用(可以设置一个flag数组,当这一行有了,就标志为1,如果没有就标志为0);
只要这一列有一个皇后,那么这一列就不能用(同样可以设置一个数组);
只要这"\"左斜线有一个皇后,那么经过思索你就会发现,这一条斜线上(x-y)上的值是一样的[你可以将这一个棋盘想象成一个坐标系,将这一条斜线想象成一个方程,而这个方程中(x-y)的值的的确确不会变化,就是一个常数值];
那么右斜线呢?右斜线中(x+y)的值是不会变的(如上);
!
以上就是规律,那么看以下代码
#include "head.h"//此处不重要,是我储存头文件的地方;
class Solution
{
public:
vector<int> rows;
vector<int> cols;
vector<int> left;
vector<int> right;
int cnt;
int array[9][9];//此处用不到;
int totalNQueens(int n)
{
//cout << 1 << endl;
//对横竖斜纵进行初始化;
rows.resize(10, 0);
cols.resize(10, 0);
left.resize(20,0);//如果好奇为什么以上都是10,而下面都是20可以看看以下代码;
right.resize(20, 0);
cnt = 0;
//cout << 1<<endl;
memset(array, 0, sizeof array);//对数组初始化,但是下面用不到;
//int k = 1; cout << 11 << endl;
find(1, n);//开始dfs,其实如果n为类成员变量的话,同样可以将n去掉;
return cnt;
}
void find(int x, int all)
{
if (x == all + 1)//边界条件,main函数中假设的是5,所以当x成了6的时候,说明前面都已经前五行都已经排满了,所以才会到达这个地步;
{
cnt++;
return;
}
int i;
for (i = 1; i <= all; i++)//对某一行的每一个点都要判断
{
if (judge(x, i))//judge用来判断是否可以放入皇后这一个位置;
{
//以下是回溯;---->我所了解的回溯就是以下这种套路,不会没关系,我递归都学了好几个月才差不多会用它做题;
set_all(x, i);//进入到这里说明可以放入,那么就标志起来,
find(x + 1, all);
can_all(x, i);//取消
}
}
}
void set_all(int x, int y)//如果(x,y)要放置皇后,那么就将这一个点的横纵斜竖全部标志为1;
{
rows[x] = 1;
cols[y] = 1;
left[x - y + 9] = 1;//这里是重点,在上面讲述技巧的时候,你会发现,如果要设置标志数组的话,(x-y)的值有可能是负数,那么避免的方法就是+n,让x-y无论如何都是正数;
right[x + y] = 1;//而此处的话,之所以要将数组设置成20,是因为(x+y)的值有可能会超过十;
}
void can_all(int x, int y)//取消;
{
rows[x] = 0;
cols[y] = 0;
left[x - y + 9] = 0;
right[x + y] = 0;
}
bool judge(int x, int y)
{
if (rows[x] == 1)
return false;
if (cols[y] == 1)
return false;
if (left[x - y + 9] == 1)
return false;
if (right[x + y] == 1)
return false;
return true;
}
};
int main()
{
Solution x;
//cout << 10 << endl;
cout << x.totalNQueens(5);
}
怎么说呢,一开始觉得这种题不适合我做,但是做出来之后异常的兴奋,毕竟上面标志的难题我做了出来(尽管!尽管做了n个小时).为了以后能找到不错的工作,我拼了!
/cout << 10 << endl;
cout << x.totalNQueens(5);
}
怎么说呢,一开始觉得这种题不适合我做,但是做出来之后异常的兴奋,毕竟上面标志的难题我做了出来(尽管!尽管做了n个小时).为了以后能找到不错的工作,我拼了!