Python学习笔记—八皇后问题

问题描述:有一个棋盘和8个要放到上面的皇后。唯一的要求是皇后之间不能形成威胁。也就是说,让皇后不能再同一行同一列或者同一个对角线。

状态表示:为了表示一个可能的解决方案,可以使用元组(或者列表)。每个元组中元素都只是相应行的皇后的列位置。如果state[0]=3,那么表示在第一行的皇后实在第四列。当某一个递归的层面(一个具体的行)时,只能知道上一行皇后的位置。因此需要一个小于8的状态元组

寻找冲突:把冲突定义成一个conflict函数(以状态组的形式),然后由函数判断下一个皇后的位置会不会有新的冲突。

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

参数nextX代表下一个皇后的水平位置(x坐标或列),nextY代表垂直位置(有坐标或列)。这个函数对前面的每个皇后的位置做一个简单的检查,如果下一个皇后和前面的皇后有同样的水平位置,或者是在一条对角线上,就会发生冲突,接着返回True。如果没有这样的冲突发生,那么返回False

abs(state[i]-nextX) in (0,nextY-i) 如果下一个皇后和正在考虑的前一个皇后的水平距离为0,或者垂直距离在同一条对角线上,就返回True,否则返回False。这个语句包含着两个比较。

如果只剩下一个皇后没有放置,那么遍历它的所有的可能的位置,并且返回没有冲突发生的位置。Num参数是皇后的总数,state参数是存放在前面的皇后的位置信息的元组。假设有4个皇后,前3个分别放置在1,3,0号位置,如图所示:


Python表示这一段:

def queeens(num=8,state=()):

    if len(state) == num-1:

        for pos in range(num):

            if not conflict(state,pos):

                yield pos

 

完整代码:

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=8,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

def prettyprint(solution):

    def line(pos , length =len(solution)):

        return '. ' * (pos) + 'X ' + '. '*(length - pos - 1)

    for pos in solution:

        print line(pos)

>>> len(list(queens(8)))

92

八皇后一共有92个解

>>> import random

>>> prettyprint(random.choice(list(queens(8))))

. . . . . . X . 

. . X . . . . . 

X . . . . . . . 

. . . . . X . . 

. . . . . . . X 

. . . . X . . . 

. X . . . . . . 

. . . X . . . . 

你可能感兴趣的:(Python学习笔记—八皇后问题)