我正在尝试解决方案中的n-queens问题。我的教授告诉我使用单个矢量作为棋盘,矢量的第i个元素代表棋盘的第i列。该元素的值是坐在后面的行,如果列为空,则为-1。因此,[0 1 2 -1 -1]有两列没有皇后和三个非法放置的皇后。 当我运行这段代码:( place-n-queens 0 4#( - 1 -1 -1 -1))我得到了#(0 1 2 3),这显然是非法放置了所有四个皇后。我认为问题在于我没有在cond中检查足够的东西 - 在Queen-on-n但是我不确定要添加什么来解决在同一对角线上获取女王的问题。
(define (return-row vector queen)
(vector-ref vector (return-col vector queen)))
(define (return-col vector queen)
(remainder queen (vector-length vector)))
(define (checkrow vector nq oq)
(cond
((= (vector-ref vector nq) -1) #f)
((= (vector-ref vector oq) -1) #f)
(else (= (return-row vector nq) (return-row vector oq)))))
(define (checkcol vector nq oq)
(= (return-col vector nq) (return-col vector oq)))
(define (checkdiagonal vector nq oq)
(cond
((= (vector-ref vector nq) -1) #f)
((= (vector-ref vector oq) -1) #f)
(else (= (abs (- (return-row vector nq) (return-row vector oq)))
(abs (- (return-col vector nq) (return-col vector oq)))))))
(define (checkdiagonalagain vector r c oq)
(= (abs (- r (return-row vector oq)))
(abs (- c (return-col vector oq)))) )
(define (checkrowagain vector r oq)
(= r (return-row vector oq)))
(define (checkinterference vector nq oq)
(or (checkrow vector nq oq) (checkcol vector nq oq) (checkdiagonal vector nq oq)))
(define (place-queen-on-n vector r c)
(local ((define (foo x)
(cond
((checkrowagain vector r x) -1)
((= c x) r)
((checkinterference vector c x) -1)
((map (lambda (y) (eq? (vector-ref vector x) y))
(build-list (vector-length vector) values)) (vector-ref vector x))
((eq? (vector-ref vector x) -1) -1)
(else -1))))
(build-vector (vector-length vector) foo)))
(define (place-a-queen vector)
(local ((define (place-queen collist rowlist)
(cond
((empty? collist) '())
((empty? rowlist) '())
(else (append (map (lambda (x) (place-queen-on-n vector x (car collist))) rowlist)
(try vector (cdr collist) rowlist)))
)))
(place-queen (get-possible-col vector) (get-possible-row (vector->list vector) vector))))
(define (try vector collist rowlist)
(cond
((empty? collist) '())
((empty? rowlist) '())
(else (append (map (lambda (x) (place-queen-on-n vector x (car collist))) rowlist)
(try vector (cdr collist) rowlist)))))
(define (get-possible-col vector)
(local ((define (get-ava index)
(cond
((= index (vector-length vector)) '())
((eq? (vector-ref vector index) -1)
(cons index (get-ava (add1 index))))
(else (get-ava (add1 index))))))
(get-ava 0)))
;list is just vector turned into a list
(define (get-possible-row list vector)
(filter positive? list)
(define (thislist) (build-list (vector-length vector) values))
(remove* list (build-list (vector-length vector) values))
)
(define (place-n-queens origination destination vector)
(cond
((= origination destination) vector)
(else (local ((define possible-steps
(place-n-queens/list (add1 origination)
destination
(place-a-queen vector))))
(cond
((boolean? possible-steps) #f)
(else possible-steps))))))
(define (place-n-queens/list origination destination boards)
(cond
((empty? boards) #f)
(else (local ((define possible-steps
(place-n-queens origination destination (car boards))))
(cond
((boolean? possible-steps) (place-n-queens/list origination destination (cdr boards)))
(else possible-steps))
))))
任何帮助都是值得赞赏的!
答案 0 :(得分:0)
这很难理解。一般来说,n-queens是通过某种回溯来完成的,我没有看到你回溯的位置。困难的部分是在使用矢量时管理副作用。在返回之前,您必须将电路板设置为先前的状态。
(define (n-queens size)
(let ((board (make-vector size -1)))
(let loop ((col 0) (row 0))
(cond ((= col size) board)
((= row size) ;;dead end
(if (= col 0) ;;if first collumn
#f ;;then no solutions
(begin (vector-set! board (- col 1) -1))
#f)))
;;else undo changes made by previous level and signal the error
((safe? col row board)
(vector-set! board col row)
(or (loop (+ col 1) 0)
;;only precede to next column if a safe position is found
(loop col (+ row 1))))
;; keep going if hit a dead end.
(else (loop col (+ row 1)))))))
写得安全吗?虽然取决于你。
也不确定为什么要从向量移动到列表。它只是真的堵塞了逻辑,所以我遇到了麻烦。另外,你应该很自在地通过矢量移动。在place-queen-on-n
中,您可以在向量上使用构建列表,以便可以在其上进行映射。
而某种矢量折叠可能更合适。此外,该映射将始终返回一个始终不为false的列表,这意味着在cond之后的任何代码都将永远不会被命中。这是你的问题,我不知道,但这是一个问题。