n皇后编程问题

n皇后编程问题是一个经典问题,记得2018年北京航空航天大学计算机学院的博士招聘的上机题目就是这个,这里给出几种实现方法:

python 复制代码
import time
import itertools

Num =  8
# Num = 12   # 8

def f1():
    def test_queens(queens):
        for x in range(Num):
            for y in range(x+1, Num):
                if abs(queens[x]-queens[y])==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([int(digit)-1 for digit in s]):
            counter += 1
    return counter


def f2():
    def conflict(state, nextX):
        nextY = len(state)
        for i in range(nextY):
            if abs(state[i]-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[x]-queen[y])==(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([x for x in f2()]))
_b = time.time()
print(_b - _a)


_a = time.time()
print(len([x for x in f3()]))
_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=[ ]作为状态保存,具体代码如下:

python 复制代码
import time
import itertools
 
Num =  8

 
def f2():
    def conflict(state, nextX):
        nextY = len(state)
        for i in range(nextY):
            if abs(state[i]-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([x for x in f2()]))
_b = time.time()
print(_b - _a)

运行结果如下:

不过考虑到即使把f2()中的yield改为return也是需要使用递归算法的,而递归算法是可以使用循环算法来替代的,于是使用循环算法修改f2()中的递归,得到如下代码:

python 复制代码
import time
 
 
def f2():
    def conflict(state, nextX):
        nextY = len(state)
        for i in range(nextY):
            if abs(state[i]-nextX) in (0, nextY-i):
                return True
        return False
 
    def queens():
        s = [[i, ] 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([x for x in f2()]))
_b = time.time()
print(_b - _a)

运行结果如下:

个人github博客地址:
https://devilmaycry812839668.github.io/

相关推荐
kaixin_learn_qt_ing14 天前
learn
杂谈
方而静2 个月前
来自地平星上的物理学
杂谈·物理
是大芒果2 个月前
2026开年重磅社会现实题材短漫剧重磅来袭《消失的程序员》
杂谈
是大芒果2 个月前
爆了!关于2026开年3位程序员接连猝死事件对普通人的启示录一
杂谈
是大芒果3 个月前
破防了!2026开年3位程序员接连猝死,最年轻26岁,29岁男主离世时,妻子正怀二胎7个月…
杂谈
兮山与4 个月前
杂谈8.0
杂谈
兮山与4 个月前
杂谈9.0
杂谈
兮山与6 个月前
杂谈6.0
杂谈
javachen__1 年前
Cursor:简单三步提高生成效率
杂谈
Angry_Panda1 年前
强化学习(on-policy)同步并行采样(on-line)的并行化效率分析
杂谈