#P2094. 桐桐的数学游戏.填空题
桐桐的数学游戏.填空题
题目描述
相信大家都听过经典的 八皇后 问题吧?这个游戏要求在一个 8×8 的棋盘上放置 8 个皇后,使 8 个皇后互相不攻击(攻击的含义是有两个皇后在同一行或同一列或同一对角线上)。
桐桐对这个游戏很感兴趣,也很快解决了这个问题。可是,她想为自己增加一点难度,于是她想求出 n 皇后的解的情况。你能帮助她吗?
输入格式
一个数 n ( 1 ≤ n ≤ 13 ),表示为 n 皇后问题。
输出格式
一个数,表示 n 皇后问题的解法总数。
样例
8
92
解题思路
因为 n*n 的棋盘上要放 n 个皇后,所以每行都要放一个皇后才能放得完 n 个,也不可能某一行放 2 个皇后,否则同一行的 2 个皇后就互相攻击了。因此,我们可以用一个数组 x[i] 来记录第 i 行的皇后是放在哪一列。
我们只需要把 x[i] 数组填完,就能得到一种放置方案。来到这里,是不是觉得这条题和桐桐的全排列有几分相似?不同的地方,是要把皇后的放置规则在 DFS 函数里体现出来。枚举 x[l] 能填什么(第 l 行的皇后的位置) 有几个影响因素:
-
这一列没有别的皇后
-
[l,x[l]] 这个格子的 “左上到右下” 斜线上没有别的皇后。之前学习二维数组的时候我们有一个知识:标识 [i,j] 的这条斜线可以通过 i-j+n 来标识,i-j+n 的取值范围是 1 到 2*n-1
-
[l,x[l]] 这个格子的 “左下到右上” 斜线上没有别的皇后。标识 [i,j] 的这条斜线可以通过 i+j-1 来标识,i+j-1 的取值范围是 1 到 2*n-1
-
因为题目只问方案数有多少个,而不是输出每一个方案的内容,所以,实际上并不需要真的去填 x[i],x 数组可以不存在。只需要标记好哪些列已经有皇后,哪些斜线有皇后就可以了。
DFS 算法尤其像枚举,DFS 是递归调用,第 i 层 DFS 调用往往是枚举方案里第 i 个变量的值。
完善程序
#include<bits/stdc++.h>
using namespace std;
bool col[14],xie1[50],xie2[50];
// col 数组用于纪录哪些列已经放了皇后
// xie1 用于记录“从左上角到右下角”斜线是否放了皇后
// xie2 用于记录“从左下角到右上角”斜线是否放了皇后
int n,ans;
void dfs(int l) // 决定第 l 行的皇后的列号
{
if(l==填空(1)) // 意味着找到了一种可行方案
填空(2);
else
{
for(int i=1;i<=n;i++)
{
if(!col[i] && !xie1[l+i-1] && !xie2[l-i+n])
{
// 第 l 行的皇后放在第 i 列。
填空(3) = true; //给第 i 列打上标记
填空(4) = true; //给“从左上角到右下角”打上标记
填空(5) = true; //给“从左下角到右上角”打上标记
dfs( 填空(6) );
填空(3) = false;
填空(4) = false;
填空(5) = false;
}
}
}
}
int main()
{
scanf("%d",&n);
dfs(填空(7));
printf("%d",ans);
return 0;
}
填空(1):{{ input(1) }}
填空(2):{{ input(2) }}
填空(3):{{ input(3) }}
填空(4):{{ input(4) }}
填空(5):{{ input(5) }}
填空(6):{{ input(6) }}
填空(7):{{ input(7) }}