【问题标题】:Python N-Queen solution explanationPython N-Queen 解决方案说明
【发布时间】:2020-03-02 12:28:05
【问题描述】:

我正在通过编程访谈元素,递归章节中的 n-queen 问题的这个非常巧妙的解决方案,但似乎无法理解特定的一段代码。如果有人可以在这里解释逻辑,那将非常有帮助。如果检查冲突的条件是我试图在这里绕开我的头,但没有成功。

def n_queens(n: int) -> List[List[int]]:
    def solve_n_queens(row):
        if row == n:
            # All queens are legally placed.
            result.append(col_placement.copy())
            return
        for col in range(n):
            # Test if a newly place queen will conflict any earlier queens place before
            # I am struggling to make sense of this if condition
            if all(abs(c - col) not in (0, row - i)
                for i, c in enumerate(col_placement[:row])):
                    col_placement[row] = col
                    solve_n_queens(row + 1)

    result: List[List[int]] = []
    col_placement = [0] * n
    solve_n_queens(0)
    return result

【问题讨论】:

  • 你从哪里得到这个代码?如果不是您自己的,请务必注明来源
  • 我从一本书里得到的。
  • 请注明作者姓名、书名、章节和页码。
  • 这真的会帮助您理解代码还是堆栈溢出规则?真的很好奇!!
  • 这段代码取自 Elements of Programming Interviews,章节是动态编程。我不知道 Stack Overflow 的人有什么问题,他们一直担心学生在作业上获得帮助。如果我在做作业时得到帮助,我很可能会寻找编码解决方案而不是解释。

标签: python-3.x recursion backtracking n-queens


【解决方案1】:

底部的测试会检查每个之前的皇后位置以查看:

  1. 如果之前的皇后列放置 == 当前列放置
  2. 如果斜率:abs(当前列 - 前一列)/(当前行 - 前一行) == 1

为了澄清,让我们更改变量名称,现在编写包含对前一行的两个比较的测试:

if all(abs(prev_col - curr_col) not in (0, curr_row - prev_row)
            for prev_row, prev_col in enumerate(col_placement[:row])):
  1. 以上是 prev_col - curr_col != 0 #queens 不在同一列中

对于 2.,由于棋盘是正方形,所有对角线斜率都等于 1。可以通过确保 delta y = delta x 来测试 1 的斜率。例如 2/2 = 1,所以 2 == 2。

对于上面重写的测试,测试是:abs(prev_col - curr_col) != curr_row - prev_row。列的 abs() 确保测试两个对角线方向;行不需要 abs(),因为 curr_row 是添加的最后一行。

        # Test if a newly place queen will conflict any earlier queens place before
        # I am struggling to make sense of this if condition
        if all(abs(c - col) not in (0, row - i)
            for i, c in enumerate(col_placement[:row])):

【讨论】:

    【解决方案2】:

    鉴于棋盘的每一行都必须有一个皇后,解决方案表示为每行中皇后的水平位置列表。此外,这个列表是从上到下构建的,所以当插入皇后时,它是迄今为止最低的皇后,并且棋盘上的所有其他皇后必须在其上方的行中。

    因此要检查是否存在冲突,只需查看三个方向:在同一列中向上、对角向上和向左、对角向上和向右。

    条件all(abs(c - col) not in (0, row - i)) 会检查这一点,到目前为止,棋盘上的每个皇后。数字i, c分别代表每个皇后的垂直和水平位置; row, col 表示当前正在检查冲突的女王的位置。

    • 同一列中的冲突意味着c - col == 0
    • 对角向上和向左的冲突表示c - col == i - row
    • 对角向上和向右的冲突意味着c - col == row - i

    所有这三个都可以通过获取c - col 并测试它是否是(0, i - row, row - i) 三个数字之一来一次检查。使用绝对值函数,这相当于测试abs(c - col)是否是两个非负数(0, row - i)之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 2020-10-12
      • 2017-11-15
      相关资源
      最近更新 更多