第四:搜索算法应用 - 四皇后问题

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第四:搜索算法应用 - 四皇后问题相关的知识,希望对你有一定的参考价值。

四皇后问题

在 n 行 n 列的国际象棋上摆放 n 个皇后,使其不能互相攻击(即任意两个皇后都不能处于同一行、同一列或同一斜线上)。请问有多少种摆法,以及如何摆放这些皇后。这就是经典的 n 皇后问题。如下图所示:


当 n=4 时就成为了四皇后问题。很明显,这种问题我们可以通过搜索技术来进行求解,例如深度优先搜索。

用回溯法,在构建解空间树的途中进行深度优先探索,当探索到某一种棋盘局部不是四皇后问题的解的时候(比如出现任意两个或两个以上的棋子在同一行/同一列/45度斜线上),就可以判断这个节点向下派生出的解空间树的节点也一定不是四皇后问题的解,这样就可以避免大量的无用功。

比如上图中第二行的第一个节点出现了两个棋子在同一斜线的情况,所以可以判断出这个节点以及这个节点向下派生出的所有节点就不再有必要进行遍历了,这样就会避免4+4×4次的完全无用功的遍历,就会大大的节省时间,再去探索第二行的第二个节点……其他的同理。

算法实现

实现找出所有可能的4皇后摆法。

预期输出:

********************
XQXX
XXXQ
QXXX
XXQX
********************
XXQX
QXXX
XXXQ
XQXX
********************

代码实现:

def make(mark):
    '''
    标记皇后的位置,例如mark[0] = 2, 表示第1行皇后放在第3列的位置
    :param mark: 皇后的位置信息
    :return: 拼接好的结果
    '''
    #初始化数组
    r = [['X' for _ in range(len(mark))] for _ in range(len(mark))]
    #将每一行中皇后的位置用‘Q’代替
    for i in mark:
        r[i][mark[i]] = 'Q'
    #枚举,将原来散的元素连接成字符串
    for k, v in enumerate(r):
        r[k] = ''.join(v)
    return r


def FourQueens(mark, cur, ret):
    '''
    深度优先搜索的方式求解四皇后问题
    :param mark:表示皇后的位置信息,例如[0,1,3,2]表示棋盘的第1行第1列,第2行第2列,
                第3行第4列,第4行第3列放置了皇后。
                例如[1, None, None, None]表示第1行第2列放置了皇后,
                其他行没有放置皇后。初始值为[None,None,None,None]
    :param cur:表示当前准备在第几行放置皇后,例如`cur=1`时,表示准备在第`2`行放置皇后。
                初始值为0
    :param ret:表示存放皇后摆放结果的列表,类型为列表。初始值为[]
    :return:无
    '''
    if cur == len(mark):
        #********* Begin *********#
        # 如果当前行是最后一行,记录一个解,并返回结束此次搜索
        ret.append(make(mark))
        return
        #********* End *********#
    # 试探处理,遍历每一列, 判断当前行的皇后应该在的位置,如果满足条件,递归调用处理下一行
    for column   in range(len(mark)):
        mark[cur], down = column  , True
        for j in range(cur):
            # 当想在当前位置放皇后会与其他皇后冲突时不放置皇后
            if mark[j] == column   or abs(column  -mark[j]) == cur - j:
                #如果差值等于0,两个皇后在同一列, 则代表冲突,
                #如果列的差值等与行的差, 两个皇后在对角线上, 则代表冲突,
                down = False
                break
        if down:
            # 准备在下一行找能放置换后的位置
            FourQueens(mark, cur+1, ret)

def solveNQueens(n):
    ret = []
    FourQueens([None] * n, 0, ret)
    return ret

if __name__ == '__main__':
    result = solveNQueens(4)
    print('*' * 20)
    for r in result:
        for f in r:
            print(f)
        print('*' * 20)

参考

https://segmentfault.com/a/1190000018389690

以上是关于第四:搜索算法应用 - 四皇后问题的主要内容,如果未能解决你的问题,请参考以下文章

八皇后问题的两个高效的算法(回溯与递归)

算法学习——DFS(暴力搜索)N皇后问题

高分求人工智能N皇后回溯算法vb程序,明早之前!

算法入门经典-第七章 例题7-4-1 拓展 n皇后问题 回溯法

暴力穷举和回溯法(八皇后问题)

程序设计与算法算法基础》《第二周 递归》N皇后问题