• 算法学习-回溯法


     
    八皇后问题是一个以国际象棋为背景的问题,如何在8*8的棋盘上放置8个皇后,使得任何一个皇后都无法直接吃掉其他的皇后。其实8皇后问题也可以推广为更为一般的n皇后问题,棋盘大小变为n*n,当n=2或者3时,是不存在解的,问题的限制有:
     
    • 所有的皇后都不能在同一行或同一列,也就是说每行或每列都只能存在一个皇后;
    • 所有的皇后都不能在对角线上,假设两个皇后的坐标为(i, j)和(k, l),明显当且仅当|i-k|=|j-l|时,两个皇后在一个对角线上。
     
    回溯法是穷尽搜索算法的一种,采用试错的思想,尝试分步骤去解决一个问题,在分步解决问题的时候,当尝试不能得到有效的解答时,取消上一步或上几步的计算,通过其他可能的分步去得到可能的答案。
     
    八皇后问题使用回溯法解决的思想是,假设某一行为当前状态,不断检查该行所有位置能否放置一个皇后:
     
    • 从一行中的第一个位置开始检查,如果不能放置,接着检查该行的第二个位置,依次检查下去,直到在该行中能够找到一个可以放置一个皇后的位置,然后保存该状态,转到下一行重复该步骤;
    • 如果检查了该行中的所有位置都不能放置一个皇后,说明上一行皇后放置的位置无法让所有的皇后找到自己的位置,需要回溯到上一行,继续将上一行中的皇后位置后移,直到找到合理的位置为止;
     
    '''print current status'''
    def print_current_status(queen):
        print "----new-result--"
        for i in range(0, max):
            line = ""
            for j in range(0, max):
                if queen[i] != j:
                    line += "-"
                else:
                    line += "*"
            print line
    
    '''judge that whether the n position can place here'''
    def can_place(n, queen):
        for i in range(0, n):
            if queen[i] == queen[n] or abs(queen[i] - queen[n]) == abs(i - n):
                return False
        return True
    
    '''recursive execute n queen problem'''
    def n_queen(n, queen):
        for i in range(0, max):
            queen[n] = i
            if can_place(n, queen):
                if n == max - 1:
                    print_current_status(queen)
                else:
                    n_queen(n + 1, queen)
    
    
    if __name__ == '__main__':
        queen = [0 for i in range(max)]
        n_queen(0, queen)
     
     
    其中核心的方法就是n_queen方法,方法接收的第一个参数就是当前已经遍历到了第n行,顺序地将第n行尝试0~max,如果期间有合适的,递归看一下n+1行是否可行;如果已经到了最后一行,就直接将数据结果输出,这就是其中的一个解;如果探索所有的可能解之后没有正确的结果,回溯至上一层,最多可能遍历8*8次(在max=8的情况下)。
     
     
    其中的一个结果数据类似(*表示皇后位置)如下所示:
    *-------
    ----*---
    -------*
    -----*--
    --*-----
    ------*-
    -*------
    ---*----
     
  • 相关阅读:
    Mac下配置Android adb环境变量
    在远程Linux上搭建jenkins
    早期渲染模板-Thymeleaf总结
    启动SpringBoot时的banner自定义修改
    MySQL密码策略及修改或忘记密码
    (转)Maven使用总结
    转-安全层开发—Shiro对比Spring Security
    JavaWeb应用-发布打成jar包和war包区别
    Gitea中常规git工作流程
    简述JSP与Servlet的区别及联系
  • 原文地址:https://www.cnblogs.com/mmaa/p/5789903.html
Copyright © 2020-2023  润新知