首先我们来看一下这个著名的八皇后问题

八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

在这个问题提出之后人们又将它扩展到了n×n格的棋盘摆放n个皇后有多少种摆法

其实这是只有在8×8出现这种问题吗?那显然不是嘛,只是发明国际象棋那哥们把棋盘设计成了8×8,再配合上下棋人的跳跃性思维于是乎产生了八皇后问题。如果当时把棋盘设计成了4×4,那现在可能就会叫4皇后问题了。

无论是几个皇后  道理都是一样的嘛。对吧

今天我们就以4×4的棋盘为例来解答这个问题

我们看上边的4×4的小棋盘,也就是八皇后棋盘的儿子哈哈

在这里对棋盘中的所有格子都进行了标号,这标号可不是我随心所欲标出来的,这是根据我们众所周知的二维数组的行列标号所标出来的。每个小方格里都有两位数字,第一位表示该格子所在的行标号(从0开始),第二位顺其自然也就是列标号了。

仔细看这张图的数字,你发现了什么规律吗?

我们把行标号定义为x,列标号定义为y。我们可以用坐标的形式来表示每一个小方格。这是我们回想初高中所学过的函数知识啦  当然这个函数不是我们编程语言中的函数哈

我们在二维坐标系中,可以根据一条直线上的两个点求得该直线的斜率,即:k(斜率)=(y2-y1)/(x2-x1)  (x1,y1)与(x2,y2)为直线上的任意两点

这里有特殊的两条直线:y=x(斜率为1) 与 y=-x(斜率为-1) 即k=1 所以:|y2-y1| = |x2-x1|

看上边这个图,回忆我们初中的数学知识是不是就一目了然啦

下边是用python实现画上图的代码,感兴趣的朋友可以回去试一试哈,很神奇的


# -*- coding: utf-8 -*-
import numpy                         #调用numpy的包
import matplotlib.pyplot as plt #调用matplotlib包中的pyplot算法
n = numpy.arange(10) 
plt.plot(n,n,color="r")         #用红色的线条
plt.show()

解决皇后的问题呢,在这说了这么多斜率干嘛呀?跑题了吧   不但没有  而且二者有很大的联系 斜率为1不就是与水平面夹角45°嘛  斜率为-1不就是与水平面夹角135°嘛 上边的图中任意斜线上的方格连成一条线正好是45°或135°。不信我们随便取两个。

我们在上边的图中任意找两个在任意斜线上的方格 比如我找(1,3)和(3,1)  连线呈45°角,可见|1-3|=|3-1|  我在找(3,2)和(1,0)同样也满足 也就是说处于同一斜线上的两个方格同时也会满足|y2-y1| = |x2-x1|。

有的朋友可能已经忘了什么斜率这些概念了  都没有关系,你只需要记住在同一斜线的两个方格存在这种列表号差的绝对值与行标号差的绝对值相等即可。

好了,该说的都说了,上代码吧

# -*- coding: utf-8 -*-

num = 0
# 八皇后摆放函数 第一个参数为一维数组 数组的每个下标代表每个皇后所摆放的行号,对应的数组中的数表示该皇后所摆放的列号
def eight_queen(arr,finish_line=0):
if finish_line == len(arr): #如果放置皇后成功的行数与数组中的元素个数一致(即棋盘的行数)则认为完成了一种摆法
global num #将上边定义的num定义为全局变量 这样才能在后边对其进行自加操作
num+=1
print("第%s种摆法:" % num)
for i in range(8):
print((i,arr[i]))
return 0
for stand in range(len(arr)): #对整个列进行扫描,将列标的标号赋值给数组中对应的元素
arr[finish_line] = stand
flag = True
for line in range(finish_line):
#判断前几行对应的这一列有没有皇后 或者当前列是否与之前的皇后处在同一斜线上 两者在之一则列加一(向右边换一列再试试)
if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:
flag = False
if flag==True:
eight_queen(arr,finish_line+1)
if __name__ == '__main__': #主函数
eight_queen([0]*8)
if num != 0:
print("一共有%s种摆法" % num)
else:
print("无解")
代码解析:运行代码,首先执行if __name__ == '__main__':下边的 eight_queen([0]*8)    
找到def eight_queen(arr,finish_line=0):第一次执行时:finish_line=0,表示我先在要往棋盘的第0行放置皇后了 进行if finish_line == len(arr):
的条件判断,数组的长度为8 而finish_line为0 显然不成立 跳过if分支 刚刚只说我要往第0行放皇后 那么具体放到第一行的那个位置呢? 别着急 我们进入到下边的for循环中(这里stand变量表示列):第一次进入for循环中 stand=0(第0列),此时:arr[0]=0;
也就是说第一个皇后等待放在第0行第0列的位置。在这里定义一个flag标志位,在后边用来判断刚刚待等待放置的皇后能否在第0行第0列的位置放置。
接下来走到了下边的for循环 line=0 而 finish_line也为0 所以不会进入循环 直接执行if语句判断标志位 我们刚刚定义的就是True 所以当然成立了。这时成功的调取了 eight_queen(arr,finish_line+1) 表示我第一个皇后放置成功了,我需要往下一行(第1行)放皇后了 这是第二次调用该函数 此时 finish_line=1 要往第1行放皇后了 大部分执行与第一次完全一致 唯一不同的就是这时需要进行刚刚没有执行的for循环了
我要往第1行的第0列放置皇后了 现在需要判断在第1行之前的0列上是否有皇后 怎么判断呢? 我刚刚把被占用列已经放到的arr这个数组中了啊 只需要判断我这次往数组中放的列原来在数组中有没有不就行了嘛
于是我们判断arr[0]==stand吗? 我们已知arr[0]为0(第0行第0列有皇后) 所以第1行第0列不能再有皇后了 继续执行循环体 判断第1行第1列能放皇后吗?arr[0]==stand显然不成立 而第1行第1列与第0行第0列正好处于同一斜线 即|1-0|=1-0 所以这个格子也不能放皇后。
继续执行循环体 判断第1行第2列能放皇后吗? 会发现if的两个条件都不满足 那当然可以放了 于是第二个皇后有着落啦 往后的每一个皇后都是这样去循环判断是否可以放置的。

程序运行结果部分截图,可见输出都是皇后摆放位置的坐标。当然如果你想解决n皇后的问题,直接把eight_queen([0]*8)中的8改成你心中的n就Ok啦。

再看下边这个程序:

# -*- coding: utf-8 -*-
arr2 =[[0, 0, 0, 0, 0, 0, 0, 0], #用二维数组来模拟那个8*8的棋盘(low到爆的办法)
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
num = 0
def eight_queen(arr,finish_line=0):
if finish_line == len(arr): #如果放置皇后成功的行数与数组中的元素个数一致(即棋盘的行数)则认为完成了一种摆法
for x in range(len(arr2)):
for y in range(len(arr2)):
arr2[x][y]=0
global num #将上边定义的num定义为全局变量 这样才能在后边对其进行自加操作
num+=1
print("第%s种摆法:" % num)
for i in range(8):
for x in range(len(arr2)):
for y in range(len(arr2)):
if i == x and arr[i]==y:
arr2[x][y] = “皇”
print(arr2)
return 0
for stand in range(len(arr)): #对整个列进行扫描,将列标的标号赋值给数组中对应的元素
arr[finish_line] = stand
flag = True
for line in range(finish_line):
if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:
flag = False
if flag==True:
eight_queen(arr,finish_line+1)
if __name__ == '__main__':
eight_queen([None]*8)
if num != 0:
print("一共有%s种摆法" % num)
else:
print("无解")

看上去比刚刚好点啦,但是还是很别扭,接下来我们引用科学计算的内容numpy来转这个数组


# -*- coding: utf-8 -*-
import numpy #引用numpy包(引之前需要安装numpy解释器)
arr2 =[[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
num = 0
def eight_queen(arr,finish_line=0):
if finish_line == len(arr): #如果放置皇后成功的行数与数组中的元素个数一致(即棋盘的行数)则认为完成了一种摆法
for x in range(len(arr2)):
for y in range(len(arr2)):
arr2[x][y]=0
global num #将上边定义的num定义为全局变量 这样才能在后边对其进行自加操作
num+=1
print("第%s种摆法:" % num)
for i in range(8):
for x in range(len(arr2)):
for y in range(len(arr2)):
if i == x and arr[i]==y:
arr2[x][y] = "皇"
arr3 = numpy.array(arr2) #将二维数组转化成array格式(就是一种格式而已,转完了就是好看)
print(arr3)
return 0
for stand in range(len(arr)): #对整个列进行扫描,将列标的标号赋值给数组中对应的元素
arr[finish_line] = stand
flag = True
for line in range(finish_line):
if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:
flag = False
if flag==True:
eight_queen(arr,finish_line+1)
if __name__ == '__main__':
eight_queen([None]*8)
if num != 0:
print("一共有%s种摆法" % num)
else:
print("无解")

这回就好看多啦是吧。
第一次写,望读者有意见多多指出。

带你轻而易举的学习python——八皇后问题的更多相关文章

  1. Python 八皇后问题

    八皇后问题描述:在一个8✖️8的棋盘上,任意摆放8个棋子,要求任意两个棋子不能在同一行,同一列,同一斜线上,问有多少种解法. 规则分析: 任意两个棋子不能在同一行比较好办,设置一个队列,队列里的每个元 ...

  2. 流动python - 八皇后问题简单解决方案

    思维: 使用DFS. 坐标的一维阵列的表达,在标行,元素列.A[i]=j它表示第一i女王就行了j柱. 以穿越线,由线(从上到下),决定其列(左到右),所以,不要推断冲突的行,和主斜线副斜线冲突. (行 ...

  3. Python学习二(生成器和八皇后算法)

    看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...

  4. python基础教程总结8——特殊方法,属性,迭代器,生成器,八皇后问题

    1. 重写一般方法和特殊的构造方法 1.1 如果一个方法在B类的一个实例中被调用(或一个属性被访问),但在B类中没有找到该方法,那么会去它的超类A里面找. class A: ... def hello ...

  5. Python解决八皇后问题

    最近看Python看得都不用tab键了,哈哈.今天看了一个经典问题--八皇后问题,说实话,以前学C.C++的时候有这个问题,但是当时不爱学,没搞会,后来算法课上又碰到,只是学会了思想,应该是学回溯法的 ...

  6. 八皇后,回溯与递归(Python实现)

    八皇后问题是十九世纪著名的数学家高斯1850年提出 .以下为python语句的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩 ...

  7. 【算法导论】八皇后问题的算法实现(C、MATLAB、Python版)

    八皇后问题是一道经典的回溯问题.问题描述如下:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8*8个方格),使它们谁也不能被吃掉?         看到这个问题,最容易想 ...

  8. python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍

    目录 python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍.md 一丶字典 1.字典的定义 2.字典的使用. 3.字典的常用方法. python学习第八讲,python ...

  9. 【算法】八皇后问题 Python实现

    [八皇后问题] 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子.皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子.在一个棋盘上如果要放八个皇后,使得她们互 ...

随机推荐

  1. Hive学习之路 (二)Hive安装

    Hive的下载 下载地址http://mirrors.hust.edu.cn/apache/ 选择合适的Hive版本进行下载,进到stable-2文件夹可以看到稳定的2.x的版本是2.3.3 Hive ...

  2. React 入门学习笔记1

    摘自阮一峰:React入门实例教程,转载请注明出处. 一. 使用React的html模板 使用React, 我们需要加载3个库,react.js, react-dom.js, 和browser.js. ...

  3. virtualbox+vagrant学习-2(command cli)-17-vagrant ssh命令

    SSH 格式: vagrant ssh [options] [name|id] [-- extra ssh args] 这将SSH导入正在运行的vagrant机器,并允许你访问机器的shell. us ...

  4. jquery mobile mobiscroll 日期插件使 用mobiscroll

    官网网站: http://www.mobiscroll.com/ http://code.google.com/p/mobiscroll/ 1.精简版Demo: 查看Demo » 下载Demo » 2 ...

  5. Jenkins+github的一次定时构建示例

    首先说明,我的电脑环境是windows,所以以下的示例是基于windows10 X64. 一.新建任务,填写名称,选择类型,点击左下角的[确定] 二.配置 1.General 2.源码管理 之前在gi ...

  6. DB2创建表、操作表等常用命令

    转载:http://hi.baidu.com/ufobject/item/7fd03aeebf7be1266dabb881 一.创建库表 1.创建库 1).创建数据语句 CREATE DATABASE ...

  7. 微信公众号开发 [03] 结合UEditor实现图文消息群发功能

    0.写在前面的话 如何实现微信平台后台管理中的,图文消息发送功能? 大概的过程如下: 通过类似表单的形式,将文章各部分内容提交到后台,封装成一个实体类,并持久化到数据库中 需要推送的时候,将不同的文章 ...

  8. javascript初学者注意事项

    注:以下属于个人学习中的理解不能保证全部正确,如果有错误以后修正. 1.javascript和c#语言一样严格区分大小写,有没有类的概念. 2.所有的变量声明都使用var,虽然能打出蓝色int,但却不 ...

  9. 新装Linux无法访问域名

    昨天新安装Linux,发现ping百度ping不通: 经查询,得知是系统没有配置DNS域名服务器,百度搜索DNS域名服务器列表: 编辑 /etc/resolv.conf 文件,添加查询到的DNS服务器 ...

  10. 基于Babylon.js编写简单的骨骼动画生成器

    使用骨骼动画技术可以将网格的顶点分配给若干骨头,通过给骨头设定关键帧和父子关系,可以赋予网格高度动态并具有传递性的变形 效果.这里结合之前的相关研究在网页端使用JavaScript实现了一个简单的骨骼 ...