htdp 28.2.4

八皇后问题:在NXN的棋盘中放置8个皇后,使之不相互攻击
相互攻击:指两个皇后处于同一行或同一列,斜线

以4X4棋盘为例

在这里插入图片描述

假设将第一个皇后放在第一个格子里,在符合条件的格子里任意挑选下一个格子

符合条件的格子:'((posn 1 2) (posn 1 3) (posn 2 2) (posn 2 3) (posn 3 1) (posn 3 2))
设置一个辅助函数形成符合条件的格子

如果下一个格子挑选(posn 1 2)(挑选列表的第一个),假设就这样一直递归下去,选(posn 1 2)失败了
那就要掉过头来重新挑选上一个,如果出现了能解决八皇后问题的情况,就直接输出true,否则就这样一直往上重新挑选。
这种算法称为回溯(backtrack),回溯是向上推导,即发现不满足条件的路径,就向上返回寻求其他的路径。最常见的回溯就是迷宫。

(define (change posn1 list)
(cond
    [(empty? list) empty]
    [else
       (local ((define pos (first list)))
            (cond
                 [(cons? pos)
                  (append (change posn1 pos)
                          (change posn1 (rest list)))]
                 [(and (posn? pos) (not (threatened? posn1 pos)))
                  (cons pos (change posn1 (rest list)))]
                 [else (change posn1 (rest list))]))]))
         

辅助函数:生成符合条件的格子列表

(define (place-queen n list)
  (placement? n list 0))

(define (placement? n list flag)
  (cond
       [(= n 0) true]
       [(empty? list) false]
       [else   (local ((define (possible? n list flag)
                         (axuliary n list flag)))        
             (cond
                    [(cons? (first list))
                     (or (placement? n (first list) flag)
                          (placement? n (rest list) flag))] ;;对所有格子进行讨论
                    [else
                         (cond
                             [(possible? n list (add1 flag))     ;;回溯
                              (axuliary n list (add1 flag))]
                             [else (placement? n (rest list) flag)])]))]))

其中(possible? n list flag)是对当前要走路径是否为解的讨论,如果可以,就走,否则,重新选择另一条路。

(define Graph (build-board 4 make-posn))

(define (axuliary n list flag)
  (cond
       [(= flag 1) (placement? (sub1 n) (change (first list) Graph) flag)]
       [else (placement? (sub1 n) (change (first list) list) flag)]))

flag变量是对list不同情况一种区分

example:
(在不加flag情况下)
选第一个格子
   ->(placement? 4 '((posn 1 2) (posn 1 3) (posn 2 2) (posn 2 3) (posn 3 1) (posn 3 2)))
   ->(axuliary n list)
   ->(placement? (sub1 n) (change (first list)  list))
   其中处理的list 是 '((posn 1 2) (posn 1 3) (posn 2 2) (posn 2 3) (posn 3 1) (posn 3 2))
   第一次处理的list应该是整个list,之后才是筛选后的list,所以要分情况讨论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值