先写一个求所有解得快速方法
- ;;;by:lihuaili 2011.11.28
- ;;;参考了网上的一些资料
- ;;;构造行列(确定当前所处位置)
- (defun make-queen (row col) (list row col))
- ;;;得到行号
- (defun get-row (queen) (car queen))
- ;;;得到列号
- (defun get-col (queen) (cadr queen))
- ;;;判断是否在同一行
- (defun same-row? (nq oq) (= (get-row nq) (get-row oq)))
- ;;;判断是否在同一列
- (defun same-col? (nq oq) (= (get-col nq) (get-col oq)))
- ;;;判断是否在同一对角线上
- (defun same-diag? (nq oq)
- (= (abs (- (get-row nq) (get-row oq)))
- (abs (- (get-col nq) (get-col oq)))
- ) ;_ 结束=
- ) ;_ 结束defun
- ;;;几个位置判断(是否受到攻击)
- (defun attacks? (nq oq)
- (or (same-row? nq oq) (same-col? nq oq) (same-diag? nq oq))
- ) ;_ 结束defun
- ;;;判断皇后是否安全
- (defun safe? (target queens)
- (cond ((null queens) T)
- ((attacks? target (car queens)) nil)
- (T (safe? target (cdr queens)))
- ) ;_ 结束cond
- ) ;_ 结束defun
- ;解算棋盘阶数为sz的皇后问题(从书写上看是递归法,实际是一种迭代法).
- (defun solve (sz)
- (defun s-rec (sz x y pos sols)
- (cond
- ; 如果先通过了最后一列,表示有了一个解.
- ; (顺便说一句,反方向是因为pos是从后向前建立的.)
- ((> x sz) (cons (reverse pos) sols))
- ; 如果先通过了最后一行,就表示失败.
- ((> y sz) sols)
- ;如果皇后安全, 继续.
- ((safe? (make-queen x y) pos)
- ; 这是一种回溯调用. 执行一次就完成一次内部调用。
- (s-rec sz
- x
- (+ y 1)
- pos
- ; 运行下一列第一行,如果有任何解决方案的结果,
- ; 他们需要传送到回溯调用
- (s-rec sz
- (+ x 1)
- 1
- ; 当考虑加入这个王后下一列的位置
- (cons (make-queen x y) pos)
- sols
- ) ;_ 结束s-rec
- ) ;_ 结束s-rec
- )
- ; 如果皇后不安全, 移到下一行.
- (T (s-rec sz x (+ y 1) pos sols))
- ) ;_ 结束cond
- ) ;_ 结束defun
- ; 开始递归.
- (s-rec sz 1 1 '() '())
- ) ;_ 结束defun
- ;;;显示n阶计算方法
- (defun show-queens (n)
- (princ "\n")
- (princ (strcat "阶次为 "
- (itoa n)
- " 的皇后问题共有:***"
- (itoa (length (solve n)))
- "***解法."
- ) ;_ 结束list
- ) ;_ 结束display
- (princ)
- ) ;_ 结束defun
- (mapcar 'show-queens '(1 2 3 4 5 6 7 8 9 10))
- ;;;(setq alllst (solve 8))
|