[ 问题 ]
在 n×n 格的棋盘上,放置 n 个皇后于 n 个格子中
使得不存在任意两个皇后位于同一行、同一列、同一斜线上
输出对应存在的摆放组数 f(n) 和摆放方式
[ SAT问题 ]
把约束条件写成逻辑表达式,向逻辑可满足性问题SAT转化
再基于DPLL或CDCL求解
[ 输出解集 ]
DPLL和CDCL为可满足性算法,不能直接产生解集和解的数量
但可以以此为基础,依次将当前解的否定纳入逻辑命题,从而计算下一组解
直至不可满足,返回storage中所有解
[ 框架思路 ]
整体主要分为四个部分:
|—— 逻辑命题转化器
|—— DPLL求解器(可满足性 + 部分命题赋值确定)
|—— 单一解生成器
|__ 单一解取反循环
- 逻辑命题转化器
对于SAT问题,可以写出相应的逻辑命题合取范式CNF
将CNF用谓词和量词逻辑重写,程序便可以扫描遍历
扫描结果存于列表q,便是向求解器输入的展开的合取范式
根据波兰表达式规则,可单次扫描完成
- DPLL求解器
DPLL本身只用于可满足性判断
但通过在赋值过程中记录赋值,并在结果为 True 的回溯结束时存储
就可以收集该单一解所要求的赋值
[N] 其中一些赋值引向 False,必须在一轮结束时舍弃,具体细节在代码部分讨论
- 单一解生成器
根据一次DPLL运行生成的已赋值变量,对求解过程删除的所有子句重新分析
去除所有已赋值变量,剩余任意赋值,便为一组解
每轮的解存进storage,并将临时容器清空进行下一轮
- 单一解取反循环
将一次运行获得的解集内全部文字取反,作为新子句纳入CNF
以新CNF重新运行DPLL
重复直至CNF不可满足,storage里便是该SAT问题的所有解
N皇后逻辑命题转化
以 P ( i , j ) P(i,j) P(i,j) 表示 ( i , j ) (i,j) (i,j) 处存在皇后, ¬ P ( i , j ) \neg P(i,j) ¬P(i,j) 表示不存在皇后
思路:先保证皇后数量
≥
N
\geq N
≥N,再添加每行、每列、每斜线不得重复的限制条件,根据抽屉原理可知去除掉了皇后数量
>
N
> N
>N 的情况
则输出的解必定是
N
N
N 个皇后且满足规则约束的情况
Q
1
Q_1
Q1:每行至少存在一个元素(保证皇后
≥
N
\geq N
≥N),每行至少一列成立
P
(
i
,
j
)
P(i,j)
P(i,j)
⋀
i
=
1
n
⋁
j
=
1
n
P
(
i
,
j
,
n
)
=
:
Q
1
\bigwedge_{i=1}^{n}\bigvee_{j=1}^{n} P(i,j,n) =: Q_1
i=1⋀nj=1⋁nP(i,j,n)=:Q1
Q 2 Q_2 Q2、 Q 3 Q_3 Q3:每行、每列不存在重复皇后
“不重复皇后” 意味着若已存在皇后可推出该行、列不再存在皇后,可以表示为 P ( i , j ) → ¬ P ( i , j ′ ) P(i,j)\rightarrow\neg P(i,j') P(i,j)→¬P(i,j′) 和 P ( i , j ) → ¬ P ( i ′ , j ) P(i,j)\rightarrow\neg P(i',j) P(i,j)→¬P(i′,j),其中 j ′ ≠ j , i ′ ≠ i j' \neq j, i' \neq i j′=j,i′=i
他们等价于 ¬ P ( i , j ) ∨ ¬ P ( i , j ′ ) \neg P(i,j)\vee\neg P(i,j') ¬P(i,j)∨¬P(i,j′) 和 ¬ P ( i , j ) ∨ ¬ P ( i ′ , j ) \neg P(i,j)\vee\neg P(i',j) ¬P(i,j)∨¬P(i′,j)
于是每行、每列的不重复可以写成
⋀
i
=
1
n
⋀
j
=
1
n
−
1
⋀
k
=
j
+
1
n
¬
P
(
i
,
j
)
∨
¬
P
(
i
,
k
)
=
:
Q
2
\bigwedge_{i=1}^{n}\bigwedge_{j=1}^{n-1}\bigwedge_{k=j+1}^{n} \neg P(i,j)\vee\neg P(i,k) =: Q_2
i=1⋀nj=1⋀n−1k=j+1⋀n¬P(i,j)∨¬P(i,k)=:Q2
⋀
j
=
1
n
⋀
i
=
1
n
−
1
⋀
k
=
j
+
1
n
¬
P
(
i
,
j
)
∨
¬
P
(
k
,
j
)
=
:
Q
3
\bigwedge_{j=1}^{n}\bigwedge_{i=1}^{n-1}\bigwedge_{k=j+1}^{n} \neg P(i,j)\vee\neg P(k,j) =: Q_3
j=1⋀ni=1⋀n−1k=j+1⋀n¬P(i,j)∨¬P(k,j)=:Q3
Q 4 Q_4 Q4、 Q 5 Q_5 Q5:每斜线不存在重复皇后
“左右斜线” 分别对应 i + j = C o n s t i+j = Const i+j=Const 和 i − j = C o n s t i-j = Const i−j=Const
在 “左下-右上斜线”中与 P ( i , j ) P(i,j) P(i,j) 相比较的元素位于 P ( i − k , j + k ) P(i-k,j+k) P(i−k,j+k) 上,其中要求 i − k ≥ 1 , j + k ≤ N i-k\geq 1, j+k\leq N i−k≥1,j+k≤N
在 “左上-右下斜线”中与 P ( i , j ) P(i,j) P(i,j) 相比较的元素位于 P ( i + k , j + k ) P(i+k,j+k) P(i+k,j+k) 上,其中要求 i + k ≤ N , j + k ≤ N i+k\leq N, j+k\leq N i+k≤N,j+k≤N
⋀
i
=
2
n
⋀
j
=
1
n
−
1
⋀
k
=
1
m
i
n
(
i
−
1
,
N
−
j
)
¬
P
(
i
,
j
)
∨
¬
P
(
i
−
k
,
j
+
k
)
=
:
Q
4
\bigwedge_{i=2}^{n}\bigwedge_{j=1}^{n-1}\bigwedge_{k=1}^{min(i-1,N-j)} \neg P(i,j)\vee\neg P(i-k,j+k) =: Q_4
i=2⋀nj=1⋀n−1k=1⋀min(i−1,N−j)¬P(i,j)∨¬P(i−k,j+k)=:Q4
⋀
i
=
1
n
−
1
⋀
j
=
2
n
⋀
k
=
1
m
i
n
(
N
−
i
,
N
−
j
)
¬
P
(
i
,
j
)
∨
¬
P
(
i
+
k
,
j
+
k
)
=
:
Q
5
\bigwedge_{i=1}^{n-1}\bigwedge_{j=2}^{n}\bigwedge_{k=1}^{min(N-i,N-j)} \neg P(i,j)\vee\neg P(i+k,j+k) =: Q_5
i=1⋀n−1j=2⋀nk=1⋀min(N−i,N−j)¬P(i,j)∨¬P(i+k,j+k)=:Q5
代码部分
https://github.com/CalciumArgon/N-Queen-Question-in-DPLL