基于深度优先算法的n皇后问题(python)

前两天上离散课,留了个有意思的作业:求解n皇后问题,并且语言不限制。由于c++学艺不精,编写复杂,java更适合面向对象,matlab已被制裁(平替北大天元没接触过),所以使用了更为简单的python来进行编写。

问题描述:

N 皇后问题源自国际象棋,所有棋子中权力最大的称为皇后,它可以直着走、横着走、斜着走(沿 45 度角),可以攻击移动途中遇到的任何棋子。N 皇后问题的具体内容是:如何将 N 个皇后摆放在 N*N 的棋盘中,使它们无法相互攻击。

为了更好理解,这里放一张从别处偷过来的图

问题分析:

n皇后问题的关键可以是在一行中或者在一列中或者同一个对角线上,有且只有一个皇后。

问题建模:

表示皇后的位置的方法

可以用一个列表来表示皇后位置mark[i] = j , 表示第i行第j列是皇后

def make(mark):
    #标记皇后位置,比如mark[0] = 2,就是第一行第三列是皇后
    r = [['N' 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

判断是否可以放置皇后

首先我们引入个变量。对于皇后在棋盘上的放置方法,我们可以把在第i 行第 j 列上有皇后时为真,否则为假。

如果出现或者情况时,则表示在一条对角线上。

mark[j] == i or abs(i-mark[j]) == cur - j

进行深度遍历

深度遍历大伙都会吧,不会的回去嗯补《数据结构》

for i in range(len(mark)):
        #遍历每一列,如果可以就进行下一行的排序
        mark[cur], down = i, True
        for j in range(cur):
            #如果冲突就不放皇后
                if mark[j] == i or abs(i-mark[j]) == cur - j:
                    down = False
                    break
        #递归
        if down == True :
                N_Queens(mark, cur+1 , ret)

代码包装

def make(mark):
    #标记皇后位置,比如mark[0] = 2,就是第一行第三列是皇后
    r = [['N' 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 N_Queens(mark, cur, ret):
    #算法类似数据结构里面的深度优先遍历
    if cur == len(mark):
        #如果最后一行,记录并输出
        ret.append(make(mark))
        return
    for i in range(len(mark)):
        #遍历每一列,如果可以就进行下一行的排序
        mark[cur], down = i, True
        for j in range(cur):
            #如果冲突就不放皇后
                if mark[j] == i or abs(i-mark[j]) == cur - j:
                    down = False
                    break
        if down == True :
            N_Queens(mark, cur+1 , ret)

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

if __name__ == '__main__':
    n = int(input("想要多少皇后的问题?"))
    result = solveNQueens(n)
    print('*' * n)
    for r in result:
        for f in r:
            print(f)
        print("*" * n)

后序

由于时间匆忙(上选修课的时候写的)后期也没有继续研究,最近看了看其他的算法,除了深度优先遍历以外,我也在想能不能用其他的算法来解决这个问题,比如:暴力搜索,把所有的情况都找出来然后一一对比是否符合,只是其时间复杂度很高(极高)并且在n极大时耗费时间量极大。(同学用cpp写的时间在n=13时用时2.6s)所以也没有兴趣继续往下探索了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值