python中级篇1:n皇后问题(回溯算法)

这篇具有很好参考价值的文章主要介绍了python中级篇1:n皇后问题(回溯算法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

hello!大家好,我是浪矢秀一。最近经历了许多事情,终于是恢复1次更新了。那么今天呢,我们来学习中级篇,需要学过不少python知识的人来学习。好了,废话不多说,我们进入今天的课程!

 文章来源地址https://www.toymoban.com/news/detail-774795.html

n皇后问题题目

在1个n*n的国际象棋棋盘上,放置n个皇后,要求:同1行、同1列、同1斜线上只能有1个皇后。

 

题目分析

既然是有很多行,分别满足不同条件,那么我们可以进行枚举每行,再枚举每列。但是,如果1行都不满足的话,就要返回上行,for循环是做不到的。那么,我们可以用回溯算法来做。

 

回溯算法

那么,什么是回溯算法呢?

很简单。举个例子吧,你去山洞探险,要找到1条通路。现在,你面前有3条路,每1条都很长。那么,你该怎么做呢?

我们只要先进去1号山洞。如果通了,就走出去了;如果没通,就返回来,尝试下个山洞。接着继续判断2号山洞,按同样的方法。最终,你一定会找到出口。

那么,这个"走不通就返回"的过程,就是类似于回溯算法。只要哪里不满足条件,就返回上一步去做。

那么,既然不能用for循环来做,我们该怎么做呢?

很简单,回溯算法最常见的做法就是递归算法了。

所谓递归算法,就是某个函数直接或间接地调用了自己,从而实现一系列算法。递归函数只要不达到条件,就一直调用自己,这是"递"。直到条件满足,再退出自己,这是"归"。

我们该怎么用递归来做这题呢?

好的,开始代码讲解。

 

代码及讲解

首先,我们要定义变量n,作为"n皇后问题"中的n。

这里用"8皇后问题"举例。

n=8 #设置n
ans=0 #保存总共有多少种解法
#这里定义递归函数Queen(x),用来输出结果
Queen(1) #调用递归函数,进行计算并输出
print(f"{n}皇后问题有{ans}种解法") #输出共有多少解法

那么,我们只要定义好递归函数Queen(x)就可以了。

那么,怎么保存每次答案呢?

我们定义整型(int)列表a。那么,a[i]就表示第i行的皇后放在第a[i]列。

因为python的列表不像C++的数组,列表不能声明长度。那么,我们可以理解为,列表没有严格意义上的长度,可以越界写,但不能越界读。如果越界读,就会报错:

IndexError: list index out of range

为了防止数组越界的现象,我们可以定义变量(其实算是常量)maxN,用于表示最大的数字。列表定义了之后有些地方可以不用,但千万不能少定义空间而数组越界。

那么,maxN差不多就定义成:

maxN=n+5

这里的数字5只是例子,只要不越界就行。

列表a的定义:

a=[0 for i in range(1,maxN+1+1,1)]

range中的stop第1个"+1"是因为range的条件是小于某数,所以要加1;第2个"+1"是因为调用的是数组下标,a[0]不用,从a[1]开始,就得多定义1个。

好了,我们开始定义Queen(x)函数。Queen(x)中的x是函数参数,代表确定第几行的皇后在第几列。在此之前,1~(x-1)行的皇后位置必须确定好,要不然没法推算。

首先,我们要判断是否产生了新的结果。如果是,则输出。

def Queen(x):
    global n,a,ans #因为n,a,ans是函数外的变量,要改变它们的值,得先global一下
    if x>n: #如果递归到了第x行,且x行大于n,就说明产生了新的结果
        ans+=1 #解法加1
        print(f"第{ans}种解法:\n") #对第ans种解法进行输出提示
        for i in range(1,n+1,1): #轮番遍历a,输出"第i行的皇后应该放在第a[i]列
            print(f"第{i}行的皇后应该放在第{a[i]}列")
        return #退出,继续计算其他可能

判断是否产生结果的方法也很简单,因为我们以后如果满足条件,就需要递归Queen(x+1)来计算下1行,所以如果参数x大于了边界n,就意味着前面不仅都满足条件,还放置完毕了,也就相当于产生了结果。

那么,如果没有产生新结果,那么,我们就需要轮番遍历第x行的每1列是否满足条件。

那么,怎么判断是否满足条件呢?

这个就不太简单了。我们需要同时满足3个条件,并且之后的也得满足。

既然这样,我们就可以定义3个布尔(bool)型列表来判断是否满足条件。

定义之前,我们得先看下它的规律。

以n=4为例,那么每个格子的位置用数对来表示就是:

(1,1) (2,1) (3,1) (4,1)
(1,2) (2,2) (3,2) (4,2)
(1,3) (2,3) (3,3) (4,3)
(1,4) (2,4) (3,4) (4,4)

首先判断"这1列是否有皇后"。这个很简单,定义布尔(bool)型列表c,c[i]表示第i列是否有皇后,True表示有,False表示没有。如果没有,就尝试放置,并把c[i]更新为True。

定义列表c:

c=[False for i in range(1,maxN+1+1,1)]

每列的问题解决了。我们来看斜线问题。

我们把从左上到右下的斜线称为主斜线,从右上到左下的斜线称为副斜线。

如何判断主对角线呢?

和列一样,我们定义列表d。那么,怎么取下标呢?

举个例子:

以:

       
(1,2)      
  (2,3)    
    (3,4)  

这条斜线为例。

你有什么发现?

没错。判断(x,j)是否与之前的冲突,就只需要判断d[x-j]就行了。但是,x-j的范围是(1-n)~(n-1),可能取负数,而下标不能为负数,所以我们要判断d[x-j+n]是否为True。如果是,就代表不能放置;如果否,就代表可以放置,再尝试放置,将d[x-j+n]更新为True。

定义列表d:

d=[False for i in range(1,2*maxN+1,1)]

主斜线的问题解决了。我们来看副斜线问题。

和列一样,我们定义列表e。那么,怎么取下标呢?

以:

      (4,1)
    (3,2)  
  (2,3)    
(1,4)      

这条斜线为例。

你发现了什么?

没错。判断(x,j)是否与以前冲突,就只需要判断e[x+j]就行了。我们要判断e[x+j]是否为True。如果是,就代表不能放置;如果否,就代表可以放置,再尝试放置,将e[x+j]更新为True。

定义列表e:

e=[False for i in range(1,maxN+1+1,1)]

好了,条件问题我们解决了。我们继续编写Queen(x)。

如果没有算出新结果,就枚举列数j作为放置位置。

for j in range(1,n+1,1):
    if((not c[j]) and (not d[x-j+n]) and (not e[x+j])): #判断是否冲突
        c[j]=d[x-j+n]=e[x+j]=True #更新冲突关系
        a[x]=j #更新放置位置
        Queen(x+1) #判断下1行
        c[j]=d[x-j+n]=e[x+j]=False #如果返回,说明下1行无法放置,就将此行位置移动
        a[x]=0 #把放置位置退出

现在,Queen(x)函数就编写好了。

Queen(x)总代码:

def Queen(x):
    global n,a,c,d,e,ans
    if x>n:
        ans+=1
        print(f"第{ans}种解法:")
        for i in range(1,n+1,1):
            print(f"第{i}行的皇后放在第{a[i]}列")
        print("")
        return
    for j in range(1,n+1,1):
        if((not c[j]) and (not d[x-j+n]) and (not e[x+j])):
            c[j]=d[x-j+n]=e[x+j]=True
            a[x]=j
            Queen(x+1)
            c[j]=d[x-j+n]=e[x+j]=False
            a[x]=0

 

完整代码:

n=8 #定义n皇后问题中的n
maxN=n+5
a=[0 for i in range(1,maxN+1,1)]
c=[False for i in range(1,maxN+1,1)]
d=[False for i in range(1,2*maxN+1,1)]
e=[False for i in range(1,2*maxN+1+1,1)]
ans=0
def Queen(x):
    global n,a,c,d,e,ans
    if x>n: #是否得到新结果
        ans+=1
        print(f"第{ans}种解法:")
        for i in range(1,n+1,1):
            print(f"第{i}行的皇后放在第{a[i]}列") #输出
        print("")
        return
    for j in range(1,n+1,1): #枚举列数
        if((not c[j]) and (not d[x-j+n]) and (not e[x+j])): #判断与之前的皇后是否冲突
            c[j]=d[x-j+n]=e[x+j]=True
            a[x]=j
            Queen(x+1) #递归,计算下1行
            c[j]=d[x-j+n]=e[x+j]=False
            a[x]=0
Queen(1) #从第1行开始计算
print(f"\n{n}皇后问题共有{ans}种解") #输出解法总和

 

好了,今天的课程就学到这里。我是浪矢秀一,关注我,带你从python小白变成编程大神!

 

到了这里,关于python中级篇1:n皇后问题(回溯算法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 回溯法--n皇后问题

    回溯法有两个模板--子集树、排列树,他们有回溯法的共同特点:深度优先搜索,如果一条路走不通,再退回来(类似递归) 八皇后问题最早是由国际象棋棋手马克斯·贝瑟尔(Max Bezzel)于1848年提出。第一个解在1850年由弗朗兹·诺克(Franz Nauck)给出。并且将其推广为更一般

    2024年02月02日
    浏览(48)
  • 回溯法求解八皇后问题

    问题提出 :八皇后问题是一个古老而著名的问题。该问题是十九世纪著名的数学家高斯1850 提出在 8x8 格的国际象棋上摆放八皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志

    2023年04月08日
    浏览(49)
  • 八皇后问题(回溯法)

    目录 什么是八皇后 八皇后问题怎么解决? 什么是回溯法 回溯法的模板 八皇后问题的核心代码 判断皇后位置是否可行 总体实现代码 每日一句: 种一棵树的最好时间是十年前,其次是现在。 八皇后问题(英文:Eight queens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的

    2023年04月09日
    浏览(34)
  • 3.2 回溯法—N皇后问题

    1. 问题描述 在 n × n ntimes n n × n 的棋盘上摆放 n n n 个皇后,使任意两个皇后都不能处于同一行、同一列或同一斜线上 2. 问题分析 下以求解4皇后问题为例,分析4皇后问题的排列树以及回溯过程: 搜索及回溯过程: 解空间树: 3. 算法设计 1. 算法思想 ①用数组x[]存放皇后的

    2024年02月04日
    浏览(35)
  • 八皇后问题,秒懂递归回溯(有图详解|c语言)

    目录 👸🏻前言 👸🏻题目介绍 👸🏻引入: 👸🏻解决思路: 👸🏻理论存在,实践开始! 👸🏻难点1:如何表示对角线被占领? 👸🏻难点2:如何用递归的方法来放皇后? 👸🏻难点3:如何实现回溯? 👸🏻难点4:如何实现皇后位置的输出? 👸🏻全部代码如下: 👸

    2024年02月02日
    浏览(29)
  • 【算法】回溯:与递归,dfs的同质与分别,剪枝与恢复现场的详细理解,n皇后的回溯解法及算法复杂度分析。

    目录 ​编辑 1.什么是回溯 2.关于剪枝 3.关于恢复现场 4.题目:二叉树的所有路径(凸显恢复现场:切实感受回溯与深搜) 问题分析 ①函数设置为:void Dfs(root) ②函数设置为:void Dfs(root,path) 解题思想:使⽤深度优先遍历(DFS)求解。 代码实现 5.N后问题 问题分析 4皇后的放置

    2024年04月16日
    浏览(37)
  • C#八皇后算法:回溯法 vs 列优先法 vs 行优先法 vs 对角线优先法

    目录 1.八皇后算法(Eight Queens Puzzle) 2.常见的八皇后算法解决方案 (1)列优先法(Column-First Method): (2)行优先法(Row-First Method): (3)对角线优先法(Diagonal-First Method): (4)回溯法(Backtracking):        皇后问题是一个古老而著名的问题,它实质上就是使棋

    2024年03月22日
    浏览(36)
  • 【力扣 51】N 皇后(回溯+剪枝+深度优先搜索)

    按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。 每一种解法包含一个不同的 n 皇后

    2024年02月22日
    浏览(34)
  • 递归算法学习——N皇后问题,单词搜索

    目录 ​编辑 一,N皇后问题 1.题意 2.解释 3.题目接口 4.解题思路及代码 二,单词搜索 1.题意 2.解释 3.题目接口 4.思路及代码 1.题意 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题  研究的是如何将  n  个皇后放置在  n×n  的

    2024年02月09日
    浏览(35)
  • Python 解决八皇后问题

       八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的 n 皇后摆放问题:这时棋

    2024年02月06日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包