我正在使用DFS进行骑士之旅。
我的问题是,当我运行它时,它可以正常工作到第20步,但在此之后算法吓坏了并在5x5板上输出(有一个5x5板的解决方案从(0,0)开始):
(1 10 5 16 24)
(4 15 2 11 20)
(9 6 17 23 22)
(14 3 8 19 12)
(7 18 13 21 25)
*法定继承人必须为0&lt; = row&lt; n和0 <=列&lt; n而不是上一步。
我的实现涉及使用genSuccessors函数生成*合法后继者,将它们抛到堆栈上并递归运行算法,并将堆栈顶部的项目作为新的当前位置。如果下一个位置是之前没有采取的步骤,我只增加step_count(负责跟踪骑士访问的方格的顺序)。当我无法生成更多的子节点时,算法会探索边界中的其他替代方案,直到前沿空(失败条件)或step_count =电路板上的#square(win)。
我认为算法一般都是合理的。
编辑:我认为问题在于,当我无法生成更多的孩子时,我去探索边境的其余部分,我需要废弃一些当前的巡演。我的问题是,我怎么知道我需要走多远?
从图形上看,在树中,我认为我需要返回到最近的节点,该节点具有到未访问的子节点的分支,并从那里重新开始,在下一个(错误的)分支时删除所访问的所有节点。它是否正确?我如何在我的代码中跟踪它?
感谢您阅读这么长的帖子;并感谢你们给我的任何帮助。
答案 0 :(得分:1)
糟糕!你的代码非常可怕。特别是:
1)它到处使用突变。 2)它试图建模&#34;返回&#34;。 3)它没有任何测试用例。
我会成为一个傲慢的小便,在这里,并简单地说这些功能组合使得难以调试的程序非常难以实现。
另外......对于DFS来说,真的没有必要跟踪你自己的堆栈;你可以使用递归,对吧?
抱歉不要提供更多帮助。
以下是我的写作方式:
#lang racket
;; a position is (make-posn x y)
(struct posn (x y) #:transparent)
(define XDIM 5)
(define YDIM 5)
(define empty-board
(for*/set ([x XDIM]
[y YDIM])
(posn x y)))
(define (add-posn a b)
(posn (+ (posn-x a) (posn-x b))
(+ (posn-y a) (posn-y b))))
;; the legal moves, represented as posns:
(define moves
(list->set
(list (posn 1 2) (posn 2 1)
(posn -1 2) (posn 2 -1)
(posn -1 -2) (posn -2 -1)
(posn 1 -2) (posn -2 1))))
;; reachable knights moves from a given posn
(define (possible-moves from-posn)
(for/set ([m moves])
(add-posn from-posn m)))
;; search loop. invariant: elements of path-taken are not
;; in the remaining set. The path taken is given in reverse order.
(define (search-loop remaining path-taken)
(cond [(set-empty? remaining) path-taken]
[else (define possibilities (set-intersect (possible-moves
(first path-taken))
remaining))
(for/or ([p possibilities])
(search-loop (set-remove remaining p)
(cons p path-taken)))]))
(search-loop (set-remove empty-board (posn 0 0)) (list (posn 0 0)))
;; start at every possible posn:
#;(for/or ([p empty-board])
(search-loop (set-remove empty-board p) (list p)))