【发布时间】:2013-06-05 07:44:29
【问题描述】:
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
不是真的在寻找代码,而是对一两个策略的简单解释,它不那么天真,并且与功能方法相得益彰。
【问题讨论】:
-
“炸毁”是什么意思?如果是Scheme实现失败,你用的是什么实现?
-
@GoZoner,最大递归错误在 n 11 或更大时开始,但在 n 10 或更低时不会出现。使用 Mit-scheme,
-
您可以增加 mit-scheme 的堆栈大小;这样做可以避免您看到的递归错误。试试
mit-scheme --stack <number-of-1024-blocks>。我知道,这并不能回答您的算法问题。 -
在视频讲座中,Hal Abelson 使用这个问题来演示流。
标签: lisp scheme sicp mit-scheme n-queens