【发布时间】:2020-08-10 17:05:55
【问题描述】:
我正在尝试编写一个 Python 程序,该程序将使用回溯解决骑士巡回赛问题。对于那些不熟悉的人:“骑士被放置在空棋盘的第一个方格上,根据国际象棋规则移动,必须准确地访问每个方格一次。”
我的代码大部分工作但不完全。它通常得到第 7 步,然后返回未完成的棋盘。为什么?
board = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
def move(x, y, count, move_x, move_y):
if count == len(board)**2:
return True
for i in range(8):
if is_valid(x + int(move_x[i]), y + int(move_y[i]), board):
if move(x + move_x[i], y + move_y[i], count + 1, move_x, move_y):
board[x][y] = count
return True
return False
def print_board(bo):
for i in range(len(bo)):
for j in range(len(bo[0])):
if j == (len(board[0]) - 1):
print(bo[i][j])
else:
print(bo[i][j], end = " ")
def is_valid(x, y, board):
if x >= 0 and y >= 0 and x < len(board) and y < len(board) and board[x][y] == 0:
return True
return False
def solve(bo):
print_board(board)
move_x = [1, 2, 2, 1, -1, -2, -2, -1]
move_y = [2, 1, -1, -2, -2, -1, 1, 2]
counter = 1
x_loc = 0
y_loc = 0
if not(move(x_loc, y_loc, counter, move_x, move_y)):
print("No solution")
else:
print(" ")
print_board(board)
solve(board)
【问题讨论】:
-
这是回溯,但不是完全递归的(或 OOP):
board是一个全局变量,move()覆盖了全局变量board。而不是声明一个类Board和一个实例board具有可以保存和恢复的内部状态。因此,这通常无法"solve" Knights Tour,它只能找到第一个解决方案。 -
另外,
move()中的 for 循环总是返回它找到的第一个合法移动(即蛮力,它不适用,例如 Warnsdorff's heuristic: choose the square with the fewest legal onward moves,这将大大减少你的组合爆炸。而不是构建所有失败状态的哈希,这将使用大量的内存。
标签: python recursion backtracking recursive-backtracking knights-tour