题目 : 八皇后 Checker Challenge
前言 : 深度优先搜索也是一种暴力枚举的算法,但是相较于循环枚举这种固定层数而且不能随意增减层数的枚举形式来说, DFS更具有优势,因为DFS是逐步扩大枚举范围,直到找到答案或无解,并且比较灵活(剪枝,记忆化等等)
所以在无法找到一个高效的降低循环枚举复杂度的策略(例如 : 动态规划,贪心,递推,公式推导等)时,深搜是一个很好的方案
思路
核心思路 : 依据题意,我们要枚举每一行棋子放的位置也就是求n的全排列 n!然后去筛选符合条件的解
对于条件每行,每列,每条对角线,最多只能有一个棋子
- 行 : 枚举n种情况,对应的就是对行的判重
- 列 : 由于是n * n的矩阵所以用
col[i]
即可判重 - 正对角线 : y = kx + b (k = 1) => b = y - x 定值(可代表一条直线也就是确保该截距的直线内没有皇后) 但是可能为负数,由于数组下标不能为负数,所以需要加上偏移量,所以用
dg[u - i + n]
- 反对角线 : y = -kx + b (k = 1) => b = y + x 定值,所以用
udg[u + i]
代码如下
#include <iostream>
using namespace std;
const int N = 100;
int a[N];
bool col[N], dg[N], udg[N]; // 列, 正对角, 反对角
int n, res;
void dfs(int u)
{
if (u > n)
{
res ++;
if (res <= 3)
{
for (int i = 1; i <= n; i ++)
printf("%d ",a[i]);
puts("");
}
}
for (int i = 1; i <= n; i ++)
{
if (!col[i] && !dg[u - i + n] && !udg[u + i])
{
col[i] = dg[u - i + n] = udg[u + i] = true;
a[u] = i;
dfs(u + 1);
col[i] = dg[u - i + n] = udg[u + i] = false;
}
}
}
int main()
{
cin >> n;
dfs(1);
printf("%d",res);
return 0;
}