zhidao 发表于 2025-2-7 03:03:59

n皇后编程问题

n皇后编程问题是一个经典问题,记得2018年北京航空航天大学计算机学院的博士招聘的上机题目就是这个,这里给出几种实现方法:
import timeimport itertoolsNum =8# Num = 12   # 8def f1():    def test_queens(queens):      for x in range(Num):            for y in range(x+1, Num):                if abs(queens-queens)==abs(x-y):                  return False      return True      counter = 0    for i in range(12345678, 87654321, 1):      s = str(i)      if "0" in s or "9" in s:            continue      if len(set(s)) != 8:            continue      if test_queens():            counter += 1    return counterdef f2():    def conflict(state, nextX):      nextY = len(state)      for i in range(nextY):            if abs(state-nextX) in (0, nextY-i):                return True      return False    def queens(num=Num, state=()):      for pos in range(num):            if not conflict(state, pos):                if len(state) == num-1:                  yield (pos, )                else:                  for result in queens(num, state+(pos, )):                        yield (pos, ) + result    return queens()def f3():    num = Num    def conflict(queen):      for x in range(num):            for y in range(x+1, num):                if abs(queen-queen)==(y-x):                  return True      return False    queens = []    for queen in itertools.permutations(range(num)):      if not conflict(queen):            queens.append(queen)    return queens_a = time.time()print(f1())_b = time.time()print(_b - _a)_a = time.time()print(len())_b = time.time()print(_b - _a)_a = time.time()print(len())_b = time.time()print(_b - _a)
上面的实现中,当n=8时,f1()函数实现、f2()函数实现、f3()函数实现的运行时间如下(单位为秒):
92
11.19756269454956
92
0.005673408508300781
92
0.019522428512573242

可以看到f1()函数的实现是f2实现的2000倍的用时,因此在下面的n=12时我们只给出f2()和f3()函数实现下的用时:
14200
4.591862201690674
14200
295.7449884414673
可以看到,f3()的实现下用时是f2()实现下的60倍。

总结:
f2()方法实现是运行时间最短的方法。
f3()方法是f2()用时的60倍。
f1()方法是f2()用时的2000倍。

不过在n=8时,也就是8皇后问题下,f2()和f3()的用时都是符合一般要求的(1秒以内或5秒以内)。


由于f2()中使用了yield,这一点并不通用,于是将其改为return,并加入sss=[ ]作为状态保存,具体代码如下:
import timeimport itertools Num =8 def f2():    def conflict(state, nextX):      nextY = len(state)      for i in range(nextY):            if abs(state-nextX) in (0, nextY-i):                return True      return False   def queens(num, state=()):      sss = []      for pos in range(num):            if not conflict(state, pos):                if len(state) == num-1:                  # yield (pos, )                  sss.append((pos,))                else:                  for result in queens(num, state+(pos, )):                        # yield (pos, ) + result                        sss.append( (pos, ) + result )      return sss    return queens(8) _a = time.time()print(len())_b = time.time()print(_b - _a)运行结果如下:



不过考虑到即使把f2()中的yield改为return也是需要使用递归算法的,而递归算法是可以使用循环算法来替代的,于是使用循环算法修改f2()中的递归,得到如下代码:
import timedef f2():    def conflict(state, nextX):      nextY = len(state)      for i in range(nextY):            if abs(state-nextX) in (0, nextY-i):                return True      return False   def queens():      s = [ for i in range(8)]# 初始化      s_tmp = []      count = 0      while count<8-1:            for state in s:                for pos in range(8):                  if not conflict(state, pos):                        state_copy = state.copy()                        state_copy.append(pos)                        s_tmp.append(state_copy)            s = s_tmp            s_tmp = []            count += 1      return s    return queens() _a = time.time()print(len())_b = time.time()print(_b - _a)运行结果如下:



个人github博客地址:
https://devilmaycry812839668.github.io/
页: [1]
查看完整版本: n皇后编程问题