Python中的生成器在八皇后问题上的应用

八皇后问题是一个经典的问题:

             为了保证各个皇后的安全,在一个8X8的矩阵上,必须保证任意两个皇后不能处于同一行、同一列以及同一条对角线上,那么安全的摆法总共有多少种呢?

好,一步步来。老话说得好,程序=数据结构+算法。我们先来选一个合适的数据结构。很明显,问题中提到了矩阵,那么二维数组肯定是可以的,但用二维数组是不是有点牛刀杀鸡的感觉?想想,8X8的矩阵我们最终只会存储8个元素,还有56个空间被浪费了。再看一下问题的条件:元素不能处于同一行,也就是每一行我们只会存储一个元素,即:f(x)=pos,x表示行号,pos表示皇后在x行的安全位置(也就是列号),而x又是连续的(1,2,3,...,8),所以说,针对这个问题,一维数组足矣:数组下标表示行号,对应值来表示位置。

好了,数据结构有了,想想算法怎么去实现。

皇后肯定是一个个的试探性的去放,如果暂时安全就放在当前位置,不安全就换一个位置试试,如果这一行都没有合适的位置,那就回到前一行,让前一行的皇后换个安全的位置,再到下一行继续试。

OK,不用多说了,典型的回溯。我们用递归来实现。

不借助迭代器,代码如下:

def poschk(pos,positions,n):
    t1=not pos in positions
    
    t2=True
    tmpx=len(positions)-1
    tmpy=pos-1
    while tmpx>=0 and tmpy>=0:
        if positions[tmpx]==tmpy:
            t2=False
            break
        tmpx-=1
        tmpy-=1
    
    t3=True
    tmpx=len(positions)-1
    tmpy=pos+1
    while tmpx>=0 and tmpy

上面的代码基本符合要求,至少所有的排列方式都能打印出来了,那么如果不想打印,而是把结果存起来呢?那就在queen函数里再加一个list参数?这样可行,但是不是有点别扭,因为这个参数在queen的绝大数调用中都是没用的,只有最后才会用来装一下结果。

好,看看Python的迭代器是怎么解决这个问题的。代码如下(除queen函数以外其他地方不变)

def queen(positions,num):
    for pos in range(num):
        t=poschk(pos,positions,num)
        if t and len(positions)==num-1:
            yield (pos,)
        if t and len(positions)

这样的话,针对排列结果就好处理多了。

比如看看有多少种排列方式:

print len(list(queen(positions,num)))   //92

你可能感兴趣的:(Python)