8个皇后的递归解决方案

时间:2012-07-17 09:58:35

标签: python algorithm recursion

我正在学习递归编码,我尝试了自己的测试 - 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)

3 个答案:

答案 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,所以在这一点上我无法帮助你,但是你可能会改变你的数据格式。