问题描述:在国际象棋中,皇后可以直走也可以斜着走,问在一个n×n的棋盘上如何放置n个皇后能使它们不能相互攻击。
解决思路:回溯法,先确定一个皇后位置,然后在其他位置确定下一个皇后,当遍历完所有位置都不能放第二个皇后时,回溯到上一个皇后,把这个皇后移动到下一个合适的位置,继续这个步骤,直到找到n个位置。
初看这个问题时我的第一反应应是挨个遍历(就是以格子为单位遍历),一想到要时间复杂度为n^n!我就知道这样做肯定太拉胯了。
后来按行为单位遍历,时间复杂度为n^n(跟上面不同在于同行的肯定不行可以在写代码时直接去掉,这个用的是子集树,还有种把同行同列的都去掉只判断是否在同斜线上,时间复杂度为n!,是排列树)
算法设计:
设计函数jisuan(n,huanghou_one=[1,1],huanghou=[])计算n皇后位置
其中参数n表示本次是计算几皇后
参数huanghou_one表示当前需判断位置(注意不是第一个皇后位置)
参数huanghou表示当前符合条件的几个皇后的位置
当huanghou中符合条件的皇后个数达到n个时,就有了这个问题的一个解
用循环来更改列数,用递归更改行数
while huagnhou_one[1] <= n:
判断皇后放在当前位置和之前已经放好的皇后冲突不
如果不冲突:
jisuan(n,[huanghou[0]+1, 1],huanghou)#即将当前位置移动到下一行第一列
huanghou_one[1] += 1
代码:
import copy
def jisuan(n, huanghou_one = [1, 1], huanghou = []):
if len(huanghou) == n:
print(huanghou)
huanghou_ones = copy.copy(huanghou_one)
huanghous = copy.copy(huanghou)
while huanghou_ones[1] <= n:
Return = 1
for i in huanghous:
if huanghou_ones[1] == i[1] or abs(huanghou_ones[0] - i[0]) == abs(huanghou_ones [1] - i[1]):
Return = 0
if Return == 1:
huanghous.append(huanghou_ones)
jisuan(n, [huanghou_ones[0] + 1, 1], huanghous)
huanghous.pop(-1)
huanghou_ones[1] += 1
def main():
jisuan(4)
if __name__ == '__main__':
main()
这样的遍历用的是树的深度优先搜索