“四骑士”难题是在3 x 3的棋盘上进行的。相对的骑士(蓝色和红色)从彼此相对的角落开始,如下所示。这个难题的目的是让对立的骑士改变3 x 3棋盘的侧面。按照通常的移动规则,骑士一次只能移动一次(在任何方向上向前移动两个正方形,然后向左或向右移动一个正方形。
Empty Board: 3 x 3 square
A B C
D E F
G H I
Start: 4 knights in 2 teams, black and white. White knights are numbers 1
and 2 starting on tiles A and C. Black knights are #'s 3 and 4 starting on
positions G and I.
A(knight1) B C(knight2)
D E F
G(knight3) H I(knight4)
End: white and black knights have exchanged starting positions
A(knight 3 or 4) B C(knight 3|4)
D E F
G(knight 1|2) H I(knight 1|2)
要使用A *,您需要估算遍历每条路径的成本,并需要低估到目标状态的剩余距离。对于路径遍历的成本,您可以使用路径长度。您将自己留在自己的设备上来设计度量,该度量使用对目标的剩余距离的低估。
您将需要设计一个不依赖于硬编码问题状态关系的扩展功能(如果使用硬编码关系,您将损失1分)。您还需要为问题状态空间中的节点设计一个数据结构。重新思考部分路径队列中元素的结构也可能会有所帮助。将累积的成本和低估的数据存储在队列中,这是明智的选择。
我有一个A *搜索算法的示例,一个删除重复结果的功能,以及(我认为)一种可以将可能的子代从每个位置移动到板上的方法。我想确认我已经正确设置了电路板,然后需要一个基于距离的成本函数,一个低估器和一个扩展函数。
; Possible move list (L shaped moves for knights)
(setf (get 'a 'children) '(h f))
(setf (get 'b 'children) '(g i))
(setf (get 'c 'children) '(d h))
(setf (get 'd 'children) '(c i))
(setf (get 'e 'children) '(nil))
(setf (get 'f 'children) '(a g))
(setf (get 'g 'children) '(b f))
(setf (get 'h 'children) '(a c))
(setf (get 'i 'children) '(b d))
; Set knights to starting positions
(setq k1 'a)
(setq k2 'c)
(setq k3 'g)
(setq k4 'i)
FINISHING STATES CONDITIONALS
(or (equal k1 'g) (equal k1 'i))
(or (equal k2 'g) (equal k1 'i))
(or (equal k3 'a) (equal k1 'c))
(or (equal k4 'a) (equal k1 'c))
; EXPAND FUNCTION
; input example (expand '(a)) -> ((H A) (F A))
(defun expand (path)
;stops cycles
(remove-if #'(lambda (path)
(member (car path) (cdr path)))
(mapcar #'(lambda (child) (cons child path))
(get (car path) 'children))))
; Betterp function NOT WORKING
(defun betterp (p1 p2) (if
(< (+ (length p1) (get (car p1) 'distance))
(+ (length p2) (get (car p2) 'distance)))
t nil))
; remove-dups fxn that removes duplicate moves
(defun remove-dups (queue)
(do* ((path (car queue) (cadr (member path queue)))
(remd (cdr queue) (cdr (member path queue))))
((null remd) queue)
(dolist (path2 remd)
(if (equal (car path2) (car path))
(setq queue (remove path2 queue)))
; A* algorithm
(defun a*1 (queue end)
(cond ((null queue) nil)
((equal end (caar queue))
(print queue)
(reverse (car queue)))
(print queue)
(a*1 (remove-dups (sort (append (expand
(car queue)) (cdr queue))
'betterp)) end))))
(defun a* (start end)
(a*1 (list (list start)) end))
; NEED COST (path length), UNDERESTIMATOR, AND EXPAND FUNCTIONS