蓝桥杯python基础:2n皇后问题

n皇后问题,用回溯遍历所有情况。
难点:

  1. 判断下一位置是否合理。
  2. 设置递归出口,第n行安全。此时cnt+1。继续回溯遍历找到所有解。

2n皇后问题

  1. 一种皇后放完后怎么保存这种皇后对下一种皇后的影响?
  2. 回溯只有要考虑上一种皇后,回溯是不是有点复杂?

我在看别人的代码时发现别人是这么写的,因为要求得所有解,所以必须遍历所有情况,所以大佬在横向循环,纵向递归,遍历了所有的情况,没有用到回溯。
精华部分如下:

def blackDfs(c, d, n, row):
    global cnt
    if row == n:
        cnt += 1
        return
    d[row] = 0

    while d[row] < n:
        if c[row][d[row]] == 1 and issafe( d, row):
            blackDfs(c, d, n, row + 1)
        d[row] += 1

里面d存储的是前面已经存储好的黑皇后的location,就像n皇后问题一样。然后每一次递归列数从0开始,将这一列的所有情况遍历完,当该行有位置是合理的,就从此处生成一个递归分支,由此就可以遍历所有情况。
完整代码如下:(从别处引用,但原代码有一些不符合蓝桥杯输入的问题和一个其它的小问题,修改一下便可通过)

可以通过的代码如下:

cnt = 0

def issafe(d, row):
    for i in range(row):
        if d[i] == d[row] or abs(i - row) == abs(d[i] - d[row]):
            return False
    return True


def blackDfs(c, d, n, row):
    global cnt                            #已经放置了n个白皇后,放置了n个黑皇后则计数
    if row == n:
        cnt += 1
        return
    d[row] = 0

    while d[row] < n:
        if c[row][d[row]] == 1 and issafe( d, row):
            blackDfs(c, d, n, row + 1)
        d[row] += 1


def dfs(a, b, n, row):
    if row == n:
        c = [[0 for i in range(n)] for i in range(n)]
        for i in range(n):
            for j in range(n):
                c[i][j] = a[i][j]  # save a to c

        for i in range(n):
            c[i][b[i]] = 0

        d = [0 for i in range(n)]
        blackDfs(c, d, n, 0)
        return

    b[row] = 0
    while b[row] < n:
        if a[row][b[row]] == 1 and issafe(b, row):
            dfs(a, b, n, row + 1)
        b[row] += 1


def main():
    n = int(input())

    a = [[0 for i in range(n)] for i in range(n)]
    b = [0 for i in range(n)]

    for i in range(n):
        tmp = input().split()
        tmp=list(map(int,tmp))
        a[i]=tmp
    dfs(a, b, n, 0)
    print(cnt)


if __name__ == '__main__':
    main()

我是个垃圾,记录下自己的总结,不然做了题就忘。

你可能感兴趣的:(蓝桥杯python基础:2n皇后问题)