sicp练习2.42 [解8皇后问题的Scheme语言实现]

代码框架来自sicp 练习2.42。算是作业吧。

 1 (define (enumerate-interval l r)
2 (if (= l r)
3 (list l)
4 (cons l (enumerate-interval (+ l 1) r))))
5
6 ;(enumerate-interval 1 10)
7
8 (define (contains? e pl)
9 (if (null? pl)
10 #f
11 (or (eq? e (car pl))
12 (contains? e (cdr pl)))))
13
14 ;检查形如(2 1 4 3 2)这样的positions list中有没有重复元素,简单办法,hash会是更好的办法。
15 (define (no-repeat? positions)
16 (if (null? positions)
17 #t
18 (and (not (contains? (car positions) (cdr positions)))
19 (no-repeat? (cdr positions)))))
20
21 ;(no-repeat? '(1 2))
22 ;(no-repeat? '(1 2 1))
23
24 ;按理说应该检查一下rest-of-queens是不是length = (- k 1)...
25 ;使用cons可以想象成把所有列往右移一列再把新的添到第一列,这样不影响safe?的判断,简单。
26 (define (addjoin-position new-row k rest-of-queens)
27 (cons new-row rest-of-queens))
28
29 (define (flatmap proc seq)
30 (foldr append () (map proc seq)))
31
32 (define (safe? k positions)
33 ;两个点在对角线上,也就是满足同一个方程x+y=n或x-y=n
34 ;所以要判断两个点是不是在同一条“左下至右上对角线”上,
35 ;只需要算出两个x-y,判断是否相等即可。左上至右下同理。
36 (define (px-y pl)
37 (map + positions (enumerate-interval 1 k)))
38 (define (px+y pl)
39 (map - positions (enumerate-interval 1 k)))
40 (and
41 (no-repeat? positions);不在同一行
42 (no-repeat? (px-y positions));不在同一条“左下至右上对角线”上
43 (no-repeat? (px+y positions));不在同一条“左上至右下对角线”上
44 ))
45
46 ;(safe? 1 '(1))
47 ;(safe? 2 '(1 2))
48 ;(safe? 3 '(1 2 3))
49 ;(safe? 4 '(3 1 4 2))
50 ;(safe? 4 '(2 4 1 3))
51
52 ;层次遍历状态空间树,剪掉每一层中不合适的分支后再扩展到下一层。
53 (define (queens board-size)
54 (define empty-board ())
55 (define (queen-cols k)
56 ;一个布局表示成一个list,形如(2 4 1 3),表示第一列为2,第二列为2,第三列为1...
57 ;queens-cols 返回((1,2,3)(2,1,3)(3,2,1))这样的布局组成的list
58 (if (= k 0)
59 (list empty-board)
60 (filter
61 (lambda (positions) (safe? k positions))
62 (flatmap
63 (lambda (reat-of-queens)
64 (map (lambda (new-row)
65 (addjoin-position new-row k reat-of-queens))
66 (enumerate-interval 1 board-size)))
67 (queen-cols (- k 1))))))
68 (queen-cols board-size))
69
70 ;(queens 4)
71 (queens 8)



posted on 2011-12-22 17:10  windydays  阅读(518)  评论(0编辑  收藏  举报

导航