N 皇后问题是一个经典的问题,在一个N×N 的棋盘上放置 N 个皇后,每行刚好放置一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击)。
上图就是一个合法的8黄后的解,N皇后问题是指:计算一共有多少种合法的方法放置N个皇后。
很显然,我们依然会用 dfs 来求解 N 皇后问题,我们的搜索策略如下。
从第 0 行开始,我们依次给每一行放置一个皇后,对于一个确定的行,我们只需要去枚举放置的列即可,在保证放置合法的情况下,一直搜索下去。
下图是 N=4 时搜索树的局部形态(这个搜索树是按照逐列放置的):
上图中每个状态下的 -2,-1,0表示的是该状态的冲突次数(在多少列或斜线发生冲突),只有当冲突次数为 0 时才是合法状态。
确定了搜索策略,我们现在还有个问题没有解决,那就是如何判断是否发生了冲突。因为我们是逐行放置的,所以行内不会有冲突,对于列也很好处理,如果某列被占用了,只需要用一个数组标记即可。
而最难处理的是同一斜线了,一种方法是我们可以直接暴力枚举这个皇后对应的两条对角线上的点,判断是否有冲突。但是这种方法,既麻烦,效率又低。下面我们介绍一种巧妙的方法。
有一个规律,这条对角线上的位置的行加列的值相同,都是4.
而这样的对角线上的位置的坐标的行减去列的值也是相同的,都是-2.
而我们发现,对于每条对角线,和值或插值都是不一样的,而我们可以正好用这个来标记一条对角线是否被占用,使得标记对角线就像标记列一样简单了。
示例代码
#include <iostream>
using namespace std;
int ans = 0;
bool row[10],x1[20],x2[20];
bool check(int c,int i){
return !row[i]&&!x1[c+i]&&!x2[c-i+8];
}
void dfs