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/

相关推荐
Angry_Panda3 天前
python实现的扫雷游戏的AI解法(启发式算法)
杂谈
伊玛目的门徒6 天前
什么是极客的情怀~~水一篇文章
杂谈·极客
Angry_Panda11 天前
如何编程求解俄罗斯方块游戏问题
杂谈
Angry_Panda3 个月前
强化学习性能测试方法:取最后10个epoch的testing epoch的均值 —— 强化学习中的一种性能测试方法
杂谈
Angry_Panda3 个月前
全双工网卡在实际工作中上下行的网速速率是否一致?千兆网卡的同时上下行速率上限是否一样,网卡速率是上下行之和还是分别等于上下行速率
杂谈
upuphaha5 个月前
各大广告商竞相厮杀下,诞生了一个偏门的副业方式
物联网·广告·杂谈·一起做事
无畏烧风8 个月前
[windows]Windows上缩放窗体的两种方式
杂谈
自己的九又四分之三站台1 年前
你知道谁是计算机之父吗?
杂谈
很久88991 年前
华为星闪联盟:引领无线通信技术创新的先锋
杂谈