AcWing 843. n-皇后问题-python
原题链接
中等
作者:
Actor丶
,
2020-02-11 19:41:12
,
所有人可见
,
阅读 1273
第一种搜索方式:按行搜索
def dfs(u):
if u==n: # 1.判断dfs停止条件:如果遍历到第n行
for i in range(n):
print("".join(g[i]))
print()
return
for i in range(n): # 2.遍历状态:从小到大遍历寻找第i列
if not cols[i] and not dg[n+i-u] and not udg[u+i]: # 3.判断能否更新
g[u][i] = "Q" # 4. 更新状态
cols[i] = dg[n+i-u] = udg[u+i] = True # 更新状态
dfs(u+1) # 5.递归dfs
cols[i] = dg[n+i-u] = udg[u+i] = False # 6. 回溯,恢复现场
g[u][i] = "." # 回溯,恢复现场
# 1.输入示例
n = int(input().strip())
# 2.初始化结果数组和状态数组
g = [["." for i in range(n)] for j in range(n)]
cols = [False for i in range(n)] # 标记列是否被标记过
dg = [False for i in range(2*n)] # 标记正对角线是否标记过皇后
udg = [False for i in range(2*n)] # 标记反对角线是否标记过皇后
# 3.开始dfs搜索
dfs(0)
第二种搜索方式:按网格搜索(python超时)
def dfs_2(x, y, s):
if y==n: # 当y==n时,自动转到下一行
x+=1;y=0
if x>=n: # !出错:判断条件(x>=n)和(s==n)不同同时放在一个if后面,否则放x>=n且s!=n时,没有遇到return语句,导致x无限增大超出栈容量
if s==n:
for i in range(n):
print("".join(g[i]))
print()
return
# !!!注意:枚举放皇后和不放皇后两种选择
dfs_2(x, y + 1, s)
if not rows[x] and not cols[y] and not dg[n+x-y] and not udg[x+y]:
# print(x,y,s)
g[x][y]="Q"
rows[x] = cols[y] = dg[n+x-y] = udg[x+y] = True
dfs_2(x,y+1,s+1)
g[x][y]="."
rows[x] = cols[y] = dg[n+x-y] = udg[x+y] = False
# 1.输入示例
n = int(input().strip())
# 2.初始化结果数组和状态数组
g = [["." for i in range(n)] for j in range(n)]
rows = [False for i in range(n)] # 标记列是否被标记过
cols = [False for i in range(n)] # 标记列是否被标记过
dg = [False for i in range(2*n)] # 标记正对角线是否标记过皇后
udg = [False for i in range(2*n)] # 标记反对角线是否标记过皇后
# 3.开始dfs搜索
dfs_2(0,0,0)
你第二种方法,你只要把不选的代码放到选的代码后面就行了。y总是先进行不选的,那样会递归到最后一个数,从后往前放皇后。而你只要先选,后不选的话。那样的话。Python就不会TLE了
是的,优秀,但我其实用python测试了一下,用的python专业版,我发现TLE的那种运行时间还比TLE的时间少了100ms,可能是因为先放皇后,能先输出完所有结果,我猜测应该是如此。我一开始还以为不选放到选后面代码是错的,想了一下,没有问题,感谢,优秀。
感谢!
第二种方法判断在网格里放皇后,那么下一步递归是不直接就可以转到下一行第一个元素
dfs_2(x+1,0,s+1)
我觉得是可以的,不过试了一下还是超时。谢谢指教!
大佬客气,你的python代码解析很好,我从中学到很多hh