这道题主要是要判断四个方向:
同行
同列
斜向1:行号加列号相同
斜向2:行号减列号的绝对值相同(也可以不用绝对值,用 +n-1 轮转)
class Solution:
def solveNQueens(self, n):
ans=[]
vis=[0]*(2*n-1) #set() #保存已经访问的行/列/斜(斜向1:行号加列号是不变的;斜向2:行号减列号相同)
b=[] #每次当前的选择,也可以用dfs中传入,但是会占用更多空间
def dfs(step):
if step==n:
l=['.'*n for _ in range(n)]
print(l)
for i in b:
print(i)
l[i[0]]=l[i[0]][:i[1]]+'Q'+l[i[0]][i[1]+1:]
ans.append(l)
return #别忘记终止
for i in range(n):
if vis[i]:#同行
continue
for j in range(n):
if vis[j]:#同列
continue
if vis[i+j]:#同斜1
continue
d=abs(i-j)
if vis[d]:#同斜2
continue
b.append([i,j])
vis[i]=1
vis[j]=1
vis[i+j]=1
vis[d]=1
''' 用set的话不方便后面恢复现场
vis.add(i)
vis.add(j)
vis.add(i+j)
'''
dfs(step+1)
b.pop()
vis[i]=0
vis[j]=0
vis[i+j]=0
vis[d]=0
#恢复现场,方便后面分支探索
dfs(0)
return ans
if __name__=='__main__':
n=4
sol=Solution()
ans=sol.solveNQueens(n)
print(ans)
我这段代码是错的,因为我没有将行号、列号、斜号进行区分
而且set是可以的,用remove就行
而且斜1和斜2不能共用一个set,否则如果 i+j = abs(i-j) 也就是其一为0的时候,会删两次报错
但是就算我开四个set还是错的
为什么呢?让我们回到题目
同行同列只有一个!那么我两层循环会导致同一行里面有多个皇后,
所以我们得把行号当作step,并在这一行里面找符合要求的位置
我们用cols来存储仍然存活的列
class Solution:
def solveNQueens(self, n):
ans = []
board = ['.' * n for _ in range(n)]
cols = set()
diag1 = set() # row + col
diag2 = set() # row - col
def dfs(row):
if row == n:
ans.append(board[:]) # 注意要复制当前棋盘!board是全局变量
return
for col in range(n):
if col in cols or (row + col) in diag1 or (row - col) in diag2:
continue
# 放置皇后
board[row] = board[row][:col] + 'Q' + board[row][col+1:]
cols.add(col)
diag1.add(row + col)
diag2.add(row - col)
dfs(row + 1)
# 回溯
board[row] = board[row][:col] + '.' + board[row][col+1:]
cols.remove(col)
diag1.remove(row + col)
diag2.remove(row - col)
dfs(0)
return ans
if __name__ == '__main__':
n = 4
sol = Solution()
ans = sol.solveNQueens(n)
for board in ans:
for row in board:
print(row)
print()