递归研究(四) 八皇后问题

皇后冲突

国际象棋棋盘(8 x 8)上的皇后(Queen)是个相当厉害的角色, 横着,竖着,斜着都可以攻击.假设两个皇后的坐标分别是(x1, y1),(x2, y2), 要想两个皇后之间不进行攻击(即两个皇后之间无冲突),要满足:

  1. x1!=x2
  2. y1!=y2
  3. |x1x2|!=|y1y2|

皇后位置表示

用8个元素的数组来表示8个皇后的最终位置,数组的索引直接对应行, 数组的值代表列,比如:

[0, 4, 7, 5, 2, 6, 1, 3]

思路

  1. 在第n行查找可以插入的位置(处理判断冲突的逻辑)
  2. 如果找到一个位置, 则放一个新的皇后, 若已经是达到最大数量, 则输出此方案
  3. 递归放置下一个皇后

代码

    #!/usr/bin/env python
    #coding:utf8

    QUEEN_MAX_NUM = 0x08

    #判断两个皇后是否攻击
    def is_attack(x1, y1, x2, y2):
        return (x1 == x2) or (y1 == y2) or ((abs(x1 - x2)) == (abs(y1 -y2)))

    #在当前状态L下, 能否在位置(row, col)处放下一个皇后而不相互攻击
    def can_put(L, row, col):
        for i in range(len(L)):
            if is_attack(i, L[i], row, col):
                return False
        return True

    #放置皇后
    def put_queen(L):
        #已经放置的皇后数
        cur_queen_count = len(L)
        for col in range(QUEEN_MAX_NUM):
            #可以在某一列放置一个皇后
            if can_put(L, cur_queen_count, col):
                T = L[::]
                T.append(col)
                #找到一个方案
                if(len(T) == QUEEN_MAX_NUM):
                    print T
                #继续递归放下一个
                else:
                    put_queen(T)

    def main():
        put_queen([])

    if __name__ == '__main__':
        main()

输出结果

92种方案:

    [0, 4, 7, 5, 2, 6, 1, 3]
    [0, 5, 7, 2, 6, 3, 1, 4]
    [0, 6, 3, 5, 7, 1, 4, 2]
    [0, 6, 4, 7, 1, 3, 5, 2]
    [1, 3, 5, 7, 2, 0, 6, 4]
    [1, 4, 6, 0, 2, 7, 5, 3]
    [1, 4, 6, 3, 0, 7, 5, 2]
    [1, 5, 0, 6, 3, 7, 2, 4]
    [1, 5, 7, 2, 0, 3, 6, 4]
    [1, 6, 2, 5, 7, 4, 0, 3]
    [1, 6, 4, 7, 0, 3, 5, 2]
    [1, 7, 5, 0, 2, 4, 6, 3]
    [2, 0, 6, 4, 7, 1, 3, 5]
    [2, 4, 1, 7, 0, 6, 3, 5]
    [2, 4, 1, 7, 5, 3, 6, 0]
    [2, 4, 6, 0, 3, 1, 7, 5]
    [2, 4, 7, 3, 0, 6, 1, 5]
    [2, 5, 1, 4, 7, 0, 6, 3]
    [2, 5, 1, 6, 0, 3, 7, 4]
    [2, 5, 1, 6, 4, 0, 7, 3]
    [2, 5, 3, 0, 7, 4, 6, 1]
    [2, 5, 3, 1, 7, 4, 6, 0]
    [2, 5, 7, 0, 3, 6, 4, 1]
    [2, 5, 7, 0, 4, 6, 1, 3]
    [2, 5, 7, 1, 3, 0, 6, 4]
    [2, 6, 1, 7, 4, 0, 3, 5]
    [2, 6, 1, 7, 5, 3, 0, 4]
    [2, 7, 3, 6, 0, 5, 1, 4]
    [3, 0, 4, 7, 1, 6, 2, 5]
    [3, 0, 4, 7, 5, 2, 6, 1]
    [3, 1, 4, 7, 5, 0, 2, 6]
    [3, 1, 6, 2, 5, 7, 0, 4]
    [3, 1, 6, 2, 5, 7, 4, 0]
    [3, 1, 6, 4, 0, 7, 5, 2]
    [3, 1, 7, 4, 6, 0, 2, 5]
    [3, 1, 7, 5, 0, 2, 4, 6]
    [3, 5, 0, 4, 1, 7, 2, 6]
    [3, 5, 7, 1, 6, 0, 2, 4]
    [3, 5, 7, 2, 0, 6, 4, 1]
    [3, 6, 0, 7, 4, 1, 5, 2]
    [3, 6, 2, 7, 1, 4, 0, 5]
    [3, 6, 4, 1, 5, 0, 2, 7]
    [3, 6, 4, 2, 0, 5, 7, 1]
    [3, 7, 0, 2, 5, 1, 6, 4]
    [3, 7, 0, 4, 6, 1, 5, 2]
    [3, 7, 4, 2, 0, 6, 1, 5]
    [4, 0, 3, 5, 7, 1, 6, 2]
    [4, 0, 7, 3, 1, 6, 2, 5]
    [4, 0, 7, 5, 2, 6, 1, 3]
    [4, 1, 3, 5, 7, 2, 0, 6]
    [4, 1, 3, 6, 2, 7, 5, 0]
    [4, 1, 5, 0, 6, 3, 7, 2]
    [4, 1, 7, 0, 3, 6, 2, 5]
    [4, 2, 0, 5, 7, 1, 3, 6]
    [4, 2, 0, 6, 1, 7, 5, 3]
    [4, 2, 7, 3, 6, 0, 5, 1]
    [4, 6, 0, 2, 7, 5, 3, 1]
    [4, 6, 0, 3, 1, 7, 5, 2]
    [4, 6, 1, 3, 7, 0, 2, 5]
    [4, 6, 1, 5, 2, 0, 3, 7]
    [4, 6, 1, 5, 2, 0, 7, 3]
    [4, 6, 3, 0, 2, 7, 5, 1]
    [4, 7, 3, 0, 2, 5, 1, 6]
    [4, 7, 3, 0, 6, 1, 5, 2]
    [5, 0, 4, 1, 7, 2, 6, 3]
    [5, 1, 6, 0, 2, 4, 7, 3]
    [5, 1, 6, 0, 3, 7, 4, 2]
    [5, 2, 0, 6, 4, 7, 1, 3]
    [5, 2, 0, 7, 3, 1, 6, 4]
    [5, 2, 0, 7, 4, 1, 3, 6]
    [5, 2, 4, 6, 0, 3, 1, 7]
    [5, 2, 4, 7, 0, 3, 1, 6]
    [5, 2, 6, 1, 3, 7, 0, 4]
    [5, 2, 6, 1, 7, 4, 0, 3]
    [5, 2, 6, 3, 0, 7, 1, 4]
    [5, 3, 0, 4, 7, 1, 6, 2]
    [5, 3, 1, 7, 4, 6, 0, 2]
    [5, 3, 6, 0, 2, 4, 1, 7]
    [5, 3, 6, 0, 7, 1, 4, 2]
    [5, 7, 1, 3, 0, 6, 4, 2]
    [6, 0, 2, 7, 5, 3, 1, 4]
    [6, 1, 3, 0, 7, 4, 2, 5]
    [6, 1, 5, 2, 0, 3, 7, 4]
    [6, 2, 0, 5, 7, 4, 1, 3]
    [6, 2, 7, 1, 4, 0, 5, 3]
    [6, 3, 1, 4, 7, 0, 2, 5]
    [6, 3, 1, 7, 5, 0, 2, 4]
    [6, 4, 2, 0, 5, 7, 1, 3]
    [7, 1, 3, 0, 6, 4, 2, 5]
    [7, 1, 4, 2, 0, 6, 3, 5]
    [7, 2, 0, 5, 1, 4, 6, 3]
    [7, 3, 0, 2, 5, 1, 6, 4]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值