SICP 包含 n-queens 解决方案的部分完整示例,通过遍历最后一行中每个可能的皇后位置的树,在下一行中生成更多可能的位置以组合迄今为止的结果,过滤可能性以仅保留那些最新的女王是安全的,并且递归地重复。
这种策略在大约 n=11 后以最大递归误差崩溃。
我已经实现了一种替代策略,该策略从第一列进行更智能的树遍历,从未使用的行列表中生成可能的位置,将每个位置列表连接到尚未使用的行的更新列表中。过滤那些被认为是安全的对,并在这些对上递归映射以用于下一列。这并没有爆炸(到目前为止),但 n=12 需要一分钟, n=13 需要大约 10 分钟才能解决。
(define (queens board-size)
(let loop ((k 1) (pp-pair (cons '() (enumerate-interval 1 board-size))))
(let ((position (car pp-pair))
(potential-rows (cdr pp-pair)))
(if (> k board-size)
(list position)
(flatmap (lambda (pp-pair) (loop (++ k) pp-pair))
(filter (lambda (pp-pair) (safe? k (car pp-pair))) ;keep only safe
(map (lambda (new-row)
(cons (adjoin-position new-row k position)
(remove-row new-row potential-rows))) ;make pp-pair
potential-rows)))))))
;auxiliary functions not listed
不是真的在寻找代码,而是对一个或两个策略的简单解释,它不那么天真,并且与功能性方法相得益彰。