n皇后问题,用回溯遍历所有情况。
难点:
- 判断下一位置是否合理。
- 设置递归出口,第n行安全。此时cnt+1。继续回溯遍历找到所有解。
2n皇后问题
- 一种皇后放完后怎么保存这种皇后对下一种皇后的影响?
- 回溯只有要考虑上一种皇后,回溯是不是有点复杂?
我在看别人的代码时发现别人是这么写的,因为要求得所有解,所以必须遍历所有情况,所以大佬在横向循环,纵向递归,遍历了所有的情况,没有用到回溯。
精华部分如下:
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()
我是个垃圾,记录下自己的总结,不然做了题就忘。