您的位置:首页 > 其它

SICP 2.42 “八皇后问题”及“n皇后问题”

2017-01-19 00:10 253 查看
八皇后问题:

在国际象棋棋盘(8x8)上,摆八个皇后,任意一个皇后都不能攻击另一个皇后(也就是说:任意两个皇后都不能在同一行,不能在同一列 ,不能在同一对角线)

递归地解释这个问题:假设我们已经生成了棋盘k-1列中k-1个皇后的所有可能方式,现在需

要的就是对其中每种方式,生成出将下一个皇后放在k列每一行的扩充集合。

把每次递归过程抽象为几步:(k-1)行前的皇后位置表和第k行组合成所有可能的位置表(map)—–筛选位置表(filter)—–递归调用函数

缩小规模,以三皇后问题为例,手动模拟递归,结果是无解(NULL)



Scheme代码:

>(define (queens board_size)
(define (queen_cols k)
(if (= k 0)
(list empty_board)
(filter
(lambda (positions) (safe? k position))
(flatmap
(lambda (rest_of_queens)
(map (lambda (new_row)
(adjoin_position new_row k rest_of_queens))
(enurmerate_interval 1 board_size))
(queen_cols (- k 1)))))))
(queen_cols board_size))


adjoin_position: 给每个已经无冲突的皇后表加入k行的坐标,每个皇后的坐标是个序对(cons x y)

> (define (adjoin_position new_row k rest_of_queens)
(map (lambda (x) (append (list x) rest_of_queens))
(map (lambda (n)
(cons k n)) new_row)))


safe: 检查生成的所有的皇后坐标表是否无冲突

> (define (safe? k positions)
(define (safe_it k y positions)
(cond ((not (pair? positions)) #t)
((= k (car (car positions))) #f)
((= 1 (/ k (car (car positions)))
(/ y (car (car positions))))
#f)
(else
(safe_it k (+ y 1) (cdr positions)))))
(safe_it k 1 (cdr positions)))


空棋盘:empty_board

(define empty_board (list '()))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  八皇后 递归 lisp Scheme