哈啰~ 大家好,今天分享一个有趣的皇后问题。

八皇后问题是西洋棋延伸而来的问题,

西洋棋的皇后是威力很大的棋子,

皇后在棋盘上的「攻击范围」为同行、同列、同对角线的地方,

要如何在8*8的方形棋盘上摆放八个皇后,使得每个皇后互相不在攻击范围中?

我们可以将问题推广为:

「如何在n*n的方形棋盘上摆放n个皇后,使得每个皇后互相不在攻击范围中?」

考量或许不是每个人都玩过西洋棋,

这边小马画个简单的示意图描述什么是皇后的「攻击范围」:

如图示,假设以红点代表皇后,

那么由该点延伸出去同行、同列、同对角线都是不能放皇后的。

给出一组八皇后问题的实例解:

(图片来源: 维基百科)

我们希望以程序找出所有不同的解。

(为了方便思考,先从小case四皇后问题想起吧)

思考重点一: 决定表达一组解的格式

在正式解问题之前,首先我们先决定如何表示一组解答,

最直觉的方式恐怕是用一个二维列表在表示整个棋盘吧,

以0表示没有放皇后,1表示有放皇后,

比如说用[[0, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0], [0, 0, 1, 0],]

表示一组放皇后的格式,

这样子最符合直觉,

可是我们发现,因为棋盘大部分的格子是不摆皇后的,

这样记录一组解其实蛮浪费空间的。

我们可以确定,

至少我们不会傻到在同一列放上两个皇后,

所以实际上我们每列用一个数字用可以记录皇后放在哪个位置了,

在上例中,皇后放在第一列index 1 的位置,第二列index 3 的位置,第三列index 0 的位置,第四列index 2 的位置,

因此,我们可以简单用阵列(1,3,0,2)来表示这组解。

思考重点二: 递迴关係(这边以python为例)

我们会想要一列一列摆放皇后,

第一列皇后位置摆好后尝试在第二列放皇后。

假设我们有一个神奇的函数queens(n, state),

n代表总共有几个皇后,

state以元组代表前已经摆好的皇后位置,

然后这个函数会回传后续所有可能的解。

譬如我们可以穷举知道四皇后问题只有(1,3,0,2),(2,0,3,1)这两组解。

(注意: 当python元组(tuple)只有一个元素,应该写(1,)而非(1))

我们期待,当我们呼叫queens(4, (1,))这个函数时,

会返回[(3,0,2)],把后续可能的皇后位置以列表形式回传。

试想,如果queens(n, state)有这样的效果,

那我们只要呼叫queens(4, ())便可以得到[(1,3,0,2), (2,0,3,1)]所有答案了。

那么该如何写递迴关係呢?

假设我们已经在第一列的index0的位置放了一个皇后:

那么扣除「攻击范围」,第二列可放的index就只有2跟3了,如图示:

仔细想想,queens(4, (0,))的所有解,不是能够由

queens(4, (0,2))的queens(4, (0,3))的所有解给拼凑出来吗?

我们试着给程序逻辑打个草稿吧:def queens(n, state): if len(state) == n: #递迴终止条件 return [()] ans = [] #记录在state棋子已经放好的状况下,后续的所有解答 for 位置 in range(n): #尝试在下一列中放新的皇后 if 这个位置不在前面皇后的攻击范围: ans 添加所有来自queens(n, state+(位置, ))的解答 return ans

嗯…逻辑大概就是这样,接着我们把细节想的更清楚一些。

细节思考: 判断皇后位置冲突

由于我们希望判断下一列中放新的皇后会不会在前面皇后的攻击范围,

我们定义一个这样的函数conflict(state, nextX),

若新皇后在任何已放置皇后的攻击范围,回传True。

比如说conflict((0,), 1)的意思是,

假设我们已经在第一列index0放了一个皇后,

再下一列index1的位置放皇后有没有事?如图示:

(以本例来说,此皇后在第一个皇后的斜对角攻击范围,应回传True)

大家可以自行做简单数学推导,

若两组(x,y)座标在同一条对角线,

x座标绝对值之差 = y座标绝对值之差。

我们的逻辑就判断两件事:若新皇后与任何旧皇后在同一行,回传True

若新皇后与任何旧皇后在同一条对角线,回传True

其余状况都返回False,

在python中可以写的很精简:def conflict(state, nextX): nextY = len(state) return any(abs(state[i] - nextX) in (0, nextY - i) for i in range(nextY))

细节思考: 收集下一列所有可能答案

刚刚queens(n, state)只是简单打了函数逻辑,

有了判断冲突的conflict函数,我们试着补上细节:def queens(n, state = ()): # 初始默认state是空棋盘 if len(state) == n: return [()] ans = [] for pos in range(n): if not conflict(state, pos): ans += [(pos,)+ result for result in queens(n, state + (pos,))] return ans

大功告成了,最后呼叫一下print(queens(4)),

应该就可以得到[(1, 3, 0, 2), (2, 0, 3, 1)]的结果啰。

两种思路- c++与python两种解

目前我共写了c++与python两种语言解n皇后问题,

各表达不同的思路,

c++是每搜索到一组解就印出来(省空间)。

python我直接用递迴一口气搜到全部的解再印出来,

都给大家参考看看

(注: 程序码中的WeiZhi就是「位置」的音译)

python语言解# 视觉化的把一组答案印出来def output(WeiZhi, num): print(f"第{num}种方案(■表示皇后):") sz = len(WeiZhi) HLINE = \' \' * 3 + \'+---\' * sz + \'+\' VLINE = (\' \' * 3 +\'|\') * (sz+1) title = \' 1\' for i in range(1,sz): title += \' \' * 3 +str(i+1) print(title) print(HLINE) for y in range(sz): print(VLINE) print(y+1, end=\' \') for x in range(sz): print(\'| ■\' if WeiZhi[y]==x else \'| 0\', end=\' \') print(\'|\') print(VLINE) print(HLINE) def conflict(state, nextX): nextY = len(state) return any(abs(state[i] - nextX) in (0, nextY - i) for i in range(nextY))def queens(n, state = ()): # 初始默认state是空棋盘 if len(state) == n: return [()] ans = [] for pos in range(n): if not conflict(state, pos): ans += [(pos,)+ result for result in queens(n, state + (pos,))] return ansqueenNUM = 4for i, q in enumerate(queens(queenNUM)): output(q, i+1)

c++语言解#include #include using namespace std;#define QUEENNUM 4int WeiZhi[QUEENNUM]; //记录每列的皇后放在第几行// 视觉化的把一组答案印出来void Output(){ static int iCount = 0; printf("第%2d种方案(★表示皇后):\\n",++iCount); cout <

No related posts.

八皇后问题初始思路python_【单人解谜】经典的八皇后问题解析相关推荐

  1. 八皇后问题初始思路python_Python 学习笔记(一)10行代码解决八皇后问题

    不引入标准库和第三方库,不用分号将多行代码写在一行,再10行代码之类求出八皇后问题的所有解. ----------------------------------------------------- ...

  2. 奥数 python_奥数赛事china夺得冠军!简单思路用Python解经典数学题

    2019年第60届国际数学奥林匹克竞赛(IMO)结果出炉,奥数大赛中国夺冠 ,中美两国同时以227的总分并列团体冠军.中国队王者归来!6名队员全部摘金,总成绩荣获世界第一! 不要错过 免费学习Pyth ...

  3. 经典问题——八皇后问题:最适合C语言初学者的解法

    什么是八皇后问题: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后 ...

  4. TCPIP详解Protocol 读书笔记(八) Traceroute程序

    TCP/IP详解:Protocol 读书笔记(八) Chapter8 Traceroute程序 文章目录 TCP/IP详解:Protocol 读书笔记(八) Chapter8 Traceroute程序 ...

  5. 2021-01-11经典的八皇后问题和N皇后问题, 回溯

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

  6. c语言八皇后问题经典算法,经典算法之八皇后问题

    八皇后问题是一个古老而又著名的问题,是学习回溯算法的一个经典案例.今天我们就一起来探究一下吧! 时间退回到1848年,国际西洋棋棋手马克斯·贝瑟尔提出了这样的一个问题, 在8×8格的国际象棋上摆放八个 ...

  7. 【×××系列八】Dynamic Multipoint *** for IPv6 详解

    [×××系列八]Dynamic Multipoint *** for IPv6 详解 一.前言 由于涉及IPV6加密,所以根据思科标准此次配置使用思科7200系列高级企业版IOS (详情参考我的上一篇 ...

  8. Java黑皮书课后题第7章:***7.36(游戏:八皇后问题)经典的八皇后难题是要将八个皇后放在棋盘上,任何两个皇后都不能相互攻击(没有两个皇后在同行、同列、同一对角线)。编写程序显示一个解决方案

    7.36(游戏:八皇后问题)经典的八皇后难题是要将八个皇后放在棋盘上,任何两个皇后都不能相互攻击(没有两个皇后在同行.同列.同一对角线).编写程序显示一个解决方案 题目 题目描述 破题 题目 题目描述 ...

  9. php论坛思路,PHP论坛实现积分系统的思路代码详解

    PHP论坛实现积分系统的思路代码详解,积分,头像,等级,用户,字段 PHP论坛实现积分系统的思路代码详解 易采站长站,站长之家为您整理了PHP论坛实现积分系统的思路代码详解的相关内容. 首先在用户表定 ...

最新文章

  1. 依赖注入容器Autofac的详解[转]
  2. 「知识表示学习」专题论文推荐 | 每周论文清单
  3. javascript基础修炼(4)——UMD规范的代码推演
  4. 程序员经典面试题,高并发系统,一般需要怎么做
  5. Nginx学习之十二-负载均衡-加权轮询策略剖析
  6. 基于python的空域变换
  7. 索尼PS5游戏主机炒到8000元以上:相比之下iPhone 12不值一提
  8. JQuery EasyUI 扩展方法 日期控件 设置时间段函数
  9. Mono 之 单元测试
  10. 京东/淘宝/苏宁试用助手Ver20210203
  11. win10修改dns服务器命令,win10怎么修改DNS服务器?win10修改DNS服务器的方法
  12. 2019 计蒜之道 初赛 第三场 - 淘宝商品价格大PK
  13. QT 代码添加QScrollArea
  14. 南航率先启用“手机登机”
  15. 面试必备:常用的设计模式总结
  16. Java霸王的大陆梦幻版_三国志霸王的大陆,喜欢三国的进
  17. 预防死锁,检测死锁,避免死锁,解除死锁....
  18. 怎样将PDF文档进行翻译?PDF文档翻译简单方法介绍
  19. element-ui表格求和求平均数
  20. NGO招志愿者翻译,请分享

热门文章

  1. 室内温湿度监测系统解决方案
  2. 计算机中的数学【线性代数】向量空间的概念
  3. 12月14日云栖精选夜读:活动推荐丨阿里云TechInsight论坛为什么这么火?
  4. Weave Scope 容器地图 - 每天5分钟玩转 Docker 容器技术(80)
  5. 手机,平板,电脑,超大屏幕 宽度响应式
  6. 【系统】windows2003 至少有一个服务或驱动程序无法加载或错误
  7. 上海交通大学软件学院2005学年度第一学期工程硕士课程安排表
  8. linux服务器重启ctrl,Linux禁止Ctrl+Alt+Del重启
  9. python numpy 数组元素周围_Python numpy数组元素属性及访问
  10. 孪生网络图像相似度_孪生网络:使用双头神经网络进行元学习