我正在学习递归编码,我尝试了自己的测试 - 8-queen拼图。我检查每一步是否存在冲突,如果存在冲突则回溯。但似乎我的代码过早地停止了回溯。
首先,我有:
0000
0000
0000
0000
然后它变为:
1000
0000
0000
0000
然后它变为:
1100
0000
0000
0000
现在冲突函数返回True,函数停止。
为什么不用solve_queen(grid)
调用:
1010
0000
0000
0000
我认为for
中的两个solve_queen(grid)
循环出了问题,但我无法准确找到出错的地方。
我的代码如下。
import copy
q4_zero = [[0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]]
def format_failed(grid):
if len(grid) != len(grid[0]):
return True
elif len(grid) < 4:
return True
return False
def row_conflict(grid):
for row in grid:
if row.count(1) > 1:
return True
return False
def col_conflict(grid):
new_grid = [[r[col] for r in grid] for col in range(len(grid[0]))]
return row_conflict(grid)
def oblique_conflict(grid):
i_lst = []
j_lst = []
row_count = len(grid)
for i in xrange(row_count):
if grid[i].count(1) > 0:
j = grid[i].index(1)
i_lst.append(i)
j_lst.append(j)
for k in xrange(len(i_lst)):
for m in xrange(len(i_lst) - 1):
if abs(i_lst[m] - i_lst[m + 1]) == abs(j_lst[m] - j_lst[m + 1]):
return True
return False
def conflict(grid):
if format_failed(grid):
return True
elif row_conflict(grid):
return True
elif col_conflict(grid):
return True
elif oblique_conflict(grid):
return True
return False
def solve_queen(__grid):
res = conflict(__grid)
if res is True:
return res
grid = copy.deepcopy(__grid)
N = len(grid)
for i in xrange(N):
for j in xrange(N):
if grid[i][j] == 0:
grid[i][j] = 1
final_answer = solve_queen(grid)
if final_answer is not True:
return final_answer
return True
return grid
print solve_queen(q4_zero)
答案 0 :(得分:1)
for i in xrange(N):
for j in xrange(N):
if grid[i][j] == 0:
grid[i][j] = 1
final_answer = solve_queen(grid)
if final_answer is not True:
return final_answer
return True
当solve_queen(grid)
为True
时,假设grid
正在返回1100
0000
0000
0000
(情况确实如此):
final_answer = True
所以,你设置final_answer is not True
。
由于未达到return True
,您跳过此行,直接转到下一行:
True
因此,您的回溯解决方案实际上是因为此行而在第一次失败后停止递归。
怎么做?
提示:你应该预先定义一个基本子句 - 当递归将保持时(提示:在你放置n个皇后之后 - 并在这种情况下返回一个答案)。
如果你发现解决方案错了 - 不要破坏它,只需继续迭代。如果您仅用尽所有可能性,则应返回return True
(因此for
语句应超出{{1}}循环的范围。)
答案 1 :(得分:1)
您永远不会将网格单元格设置为零。那么回溯应该如何起作用呢?
此外,您在solve_queen()
中有一个嵌套循环,但solve_queen()
应该是一个递归函数。使用循环或使用递归。
此外,solve_queen()
中没有暂停条件。除了conflict()
之外,您还需要一个函数is_solved()
来告诉您何时停止:
if not is_solved(grid):
return solve_queen(grid)
else return grid
在旁注中,皇后问题更有效地表示为整数数组,其中索引表示行,值表示列。例如,grid [3]会告诉你第4行中女王的相关列。
使用此表示法可以更轻松地检查冲突。此外,你节省了空间,如果从4个女王到100亿,这可能会派上用场。 ; - )
最后,你一定要阅读有关递归和回溯的内容。我怀疑你是否真的理解这些概念。
答案 2 :(得分:0)
我不知道这是否会有所帮助,但是......你尝试过不同的数据表示吗?
8-queen问题不需要整个8x8网格。由于每个女王将进入一个不同的行,你只需要一个带有女王专栏的8阵列。
我不懂Python,所以在这一点上我无法帮助你,但是你可能会改变你的数据格式。