回溯算法

回溯算法思想:

回溯算法是深度优先策略的典型应用,回溯算法就是沿着一条路向下走,如果此路不通了,则回溯到上一个分岔路,再选另一条路走,一直这样递归下去,直到遍历所有路径。回溯算法是遍历算法的一种,也是一种暴力解法。

典型应用:

【八皇后问题】在8*8的国际象棋上摆放八个皇后,使其不能互相的攻击。也就是说,任意的两个皇后不能放在同一行、同一个列或者同一个对角线上,问有多少种摆放的方法。

思路:
本算法的思路是按行来规定皇后位置,第一行放置一个皇后,第二行放置一个皇后, 第N行也放置一个皇后… 这样, 可以保证每行都有一个皇后,那么各行的皇后应该放置在哪一列呢, 算法通过循环来完成,在循环的过程中, 一旦找到一个合适的列,则该行的皇后位置确定,则继续进行下一行的皇后的位置的确定。由于每一行确定皇后位置的方式相似,所以可以使用递归法。一旦最后一行的皇后位置确定,则可以得到一组解。找到一组解之后, 之前确定皇后应该放置在哪一列的循环其实才进行了一轮循环, 算法通过该循环遍历所有的列,以此确定每一行所有可能的列的位置。在从一轮循环进入下一轮循环之前,算法需要清除在上一轮被标记为不可放置皇后的标记,也就是回溯。因为进入下一轮循环之后,同一行的皇后的列的位置会发生了变化,之前被标记为不可放置皇后的列和正反对角线位置都已经失效。

import random

# 检查当前皇后的位置与之前的皇后是否冲突
def conflict(state, nextX):
    nextY = len(state)
    for i in range(nextY):
        if abs(state[i]-nextX) in (0, nextY-i):
        # state[i]-nextX == 0:位于同一列冲突
        # state[i]-nextX == nextY-i:位于对角线冲突
            return True
    return False

# 八皇后问题的回溯算法
# 每行放置一个皇后,对列的位置进行确定
def queens(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

# 随机打印一种解法
def prettyprint(solution):
    def line(pos, length=len(solution)):
        return '. ' * (pos) + 'X ' + '. '*(length-pos-1)
    for pos in solution:
        print(line(pos))

if __name__ == "__main__":
   print (list(queens(8)))
   print("八皇后问题有", len(list(queens(8))), "种解法")
   prettyprint(random.choice(list(queens(8)))) 

运行结果:

[(0, 4, 7, 5, 2, 6, 1, 3), (0, 5, 7, 2, 6, 3, 1, 4), (0, 6, 3, 5, 7, 1, 4, 2),...]
八皇后问题有 92 种解法
. . . X . . . . 
. . . . . X . . 
X . . . . . . . 
. . . . X . . . 
. X . . . . . . 
. . . . . . . X 
. . X . . . . . 
. . . . . . X . 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值