当前位置: 首页 > 编程日记 > 正文

带你轻而易举的学习python——八皇后问题

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

八皇后问题:在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+=1print("第%s种摆法:" % num)for i in range(8):print((i,arr[i]))return 0for stand in range(len(arr)):                   #对整个列进行扫描,将列标的标号赋值给数组中对应的元素arr[finish_line] = standflag = Truefor line in range(finish_line):#判断前几行对应的这一列有没有皇后 或者当前列是否与之前的皇后处在同一斜线上 两者在之一则列加一(向右边换一列再试试)if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:flag = Falseif 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]=0global num #将上边定义的num定义为全局变量 这样才能在后边对其进行自加操作num+=1print("第%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 0for stand in range(len(arr)): #对整个列进行扫描,将列标的标号赋值给数组中对应的元素arr[finish_line] = standflag = Truefor line in range(finish_line):if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:flag = Falseif 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]=0global num                                  #将上边定义的num定义为全局变量  这样才能在后边对其进行自加操作num+=1print("第%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 0for stand in range(len(arr)):                   #对整个列进行扫描,将列标的标号赋值给数组中对应的元素arr[finish_line] = standflag = Truefor line in range(finish_line):if arr[line] == stand or abs(arr[line]-stand) == finish_line-line:flag = Falseif flag==True:eight_queen(arr,finish_line+1)
if __name__ == '__main__':eight_queen([None]*8)if num != 0:print("一共有%s种摆法" % num)else:print("无解")

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

转载于:https://www.cnblogs.com/labixiaohei/p/9965864.html

相关文章:

ubuntu18.04.1内核升级至5.0.0-25版本

ubuntu18.04操作系统版本先已支持在线的内核版本升级,到目前为止18.04发布版已经拥有三个小版本了1,2,3。 其中18.04.01和18.04.03版本,安装好之后默认的是4.15内核版本,但是默认支持在线安装4.18和5.0.0内核版本。 具体升级步骤如下&#x…

输出n行杨辉三角数

1 /*2 输出n行杨辉三角数 3 输入n&#xff0c;n是1&#xff5e;100之间的整数 4 */5 #include<stdio.h>6 int main()7 {8 int a[100],b[100];9 int i,j; 10 int n; 11 scanf("%d",&n); 12 if(n1) 13 { 14 printf("1\…

怎么扫描_打印机上扫描仪怎么用 打印机上扫描仪使用及添加方法

打印机是生活中常用的打印设备&#xff0c;主要用于连接 电脑 打印电脑上的文件&#xff0c;方便办公。对于第一次使用打印机的朋友可能还不是很熟悉如何使用&#xff0c;比如打印机上 扫描仪 怎么用&#xff1f;怎么添加打印机扫描仪&#xff1f;下面小编就来为大家介绍下吧。…

java 调用webservice的各种方法总结

http://www.blogjava.net/zjhiphop/archive/2009/04/29/webservice.html 现在webservice加xml技术已经逐渐成熟&#xff0c;但要真正要用起来还需时日!! 由于毕业设计缘故&#xff0c;我看了很多关于webservice方面的知识&#xff0c;今天和大家一起来研究研究webservice的…

vc++图像保存,重绘

新建mfc应用程序&#xff0c;单文档 增加绘图 分别增加命令响应 添加成员变量UINIT 图形可以运行&#xff0c;如何保存呢&#xff1f;&#xff08;一个集合类&#xff0c;CPtArt&#xff09; 用一个类的对象来保存一个图形的三个要素 所以插入一个新的类&#xff08;通常的类&a…

linux 进程内存分布及 堆分配和栈分配的特点

文章目录进程内存空间分布size命令查看内存分布堆方式内存分配和栈方式内存分配比较使用stap 深入追踪malloc逻辑进程内存空间分布 一个程序的内存空间主要如下&#xff1a; 代码段(text segment)&#xff1a;只读权限&#xff1b;常是指用来存放程序执行代码的一块内存区域&…

echarts 坐标自适应_echarts 同一页面,多个图表 页面大小自适应

// 路径配置require.config({paths: {echarts: ./js}});// 使用require([echarts,echarts/chart/line, // 折线图echarts/chart/bar // 柱状图],function (ec) {var myChart ec.init(document.getElementByIdx_x(main));var myChartx ec.init(document.getElementByIdx_x(main…

opencv——pcb上寻找mark点(拟合椭圆的方法)

#include "stdafx.h" // FitCircle.cpp : 定义控制台应用程序的入口#include "cv.h" #include "highgui.h" #include "cxcore.h" #include "cvaux.h" #include <iostream>using namespace cv; using namespace std; v…

bit,Byte、KB、MB、GB、TB、PB、EB之间的关系

计算机存储信息的最小单位&#xff0c;称之为位&#xff08;bit&#xff09;&#xff0c;音译比特&#xff0c;二进制的一个“0”或一个“1”叫一位&#xff1b;计算机存储容量基本单位是字节&#xff08;Byte&#xff09;&#xff0c;音译为拜特&#xff0c;8个二进制位组成1个…

echarts 点亮中国插件研究

echarts 真的是个神奇的东西&#xff0c;最近做了一个需要点亮中国的移动端项目&#xff0c;前期就怎样点亮中国做了调研&#xff0c;发现微博当初炫酷的点亮效果就是用echarts做的&#xff0c;于是研究了一下。 一连研究了一堆demo&#xff0c;不管从官网还是GitHub上面&#…

linux进程间通信:无名管道 pipe

文章目录内核层实现结构通信原理特点使用函数声明使用实例单向通信双向通信编程注意事项管道中无数据时读操作会阻塞将管道的写端句柄关闭&#xff0c;不会影响读端数据读取管道中没有数据&#xff0c;写操作关闭则读操作会立即返回管道大小测试 64K管道发生写满阻塞&#xff0…

争吵所达到的效果要_悟空:不要害怕争吵,有时候争吵一些不喜欢的事情也能创造和谐...

悟空&#xff1a;八戒&#xff0c;你吃了早饭去把马喂了吧。八戒&#xff1a;好的。悟空&#xff1a;喂了马你去看看我们午饭可以吃什么&#xff0c;如果有需要提前做预备的什么事儿&#xff0c;你知道该怎么做吧&#xff1f;八戒&#xff1a;好的。悟空&#xff1a;昨天&#…

Log4j日志管理的用法

参考网址&#xff1a; http://www.blogjava.net/314508313/archive/2011/11/14/363653.html http://www.cnblogs.com/likwo/archive/2010/09/01/1814994.html http://fanqiang.chinaunix.net/app/other/2006-06-22/4640.shtml http://www.blogjava.net/rickhunter/articles/281…

多线程实现生产者消费者模型

首先是一个仓库接口&#xff0c;该接口规定的仓库大小&#xff0c;仓库的存取方法&#xff0c;如下所示 1 package pers.lan.jc.pc;2 3 /**4 * author lan [1728209643qq.com]5 * create 2018-11-27 15:596 * desc 仓库7 */8 public interface Repertory<T> {9 10 …

再记一次ceph object unfound的艰辛历程

文章目录先说问题&#xff1a;再说解决尝试1&#xff1a;尝试2(该尝试建议先在自己环境搭配对应业务测试通过后再现场尝试)&#xff1a;感谢 学无止境996同学的陪伴和vigourtyy美丽女友的支持&#xff0c;直到这个解决问题的深夜先说问题&#xff1a; ceph 12.2.1生产环境&…

2014-01-04 SQL练习

目标数据库 250,czzznew/czzznew *关于执行计划&#xff1a;在PL/SQL选中查询的语句后&#xff0c;按下F5即可&#xff0c;其中Cost列表示当前操作的代价&#xff08;消耗&#xff09;&#xff0c;值越大代表性能越差 t_rkxx表 (1):用2种以上方法查出xm(姓名)为test或者Test的人…

多重集表示合json数据_计数DP(划分数,多重集组合数)

划分数&#xff1a;把n个无区别的物品划分成不超过m组。 dp[i][j]j的i划分的总数。 dp[i[j]dp[i][j-i]dp[i-1][j] 即&#xff1a;将j个物品分成i份&#xff0c;有两种情况&#xff1a;每份划分都大于等于1 dp[i][j-i]; 存在有一份以上用0划分dp[i-1][j]int main(){int n,m;cin&…

搭建PHP环境遇到的问题!!

为什么80%的码农都做不了架构师&#xff1f;>>> 问题1&#xff1a; 再次./configure以下错误发生 configure: error: xml2-config not found. Please check your libxml2 installation. 解决方法&#xff1a; 安装libxml2 # yum install libxml2-devel 问题2&…

linux进程间通信:shell管道 | 的实现

文章目录介绍重定向函数介绍总结linux terminal输入如下命令&#xff0c;其中"|"符号即为我们上文中所说的无名管道介绍 正如我们上文中所描述的"|“无名管道提供了具有亲缘关系的进程之间的通信&#xff0c;它由于直接使用系统调用&#xff0c;运行效率较高。…

Golang的接口

当一只鸟走路像鸭子&#xff0c;游泳像鸭子&#xff0c;叫起来也像鸭子&#xff0c;那么我们就认为它就是鸭子。 Duck typing 的理念因此比喻得名。 Golang 通过 interface 实现 duck typing。 Effective Go 文章中这样描述 interface: interface 指定了一种描述对象行为的方法…

mysql 5.6.15_mysql-5.6.15-win32.zip免安装配置

此随笔是根据网上的资料整理的&#xff1a;环境&#xff1a;Windows XP系统软件来源&#xff1a;mysql官网下载1.下载mysql-5.6.15-win32.zip&#xff1b;2.解压MySQL压缩包&#xff1b;以下以加压到“F:\Program Files\Mysql\mysql-5.6.15-win32”为例&#xff1a;3.将解压目录…

jquery treeview 树形插件

jquery treeview 插件参数说明 treeview开源地址&#xff1a;https://github.com/jzaefferer/jquery-treeview 1、animated&#xff1a;String or Number 设置展开子节点时的显示速度&#xff0c;有 slow、normal、fast 或者指定速度值&#xff0c;与 jQuery 的 hide&#xff0…

spark调优(一)-开发调优,数据倾斜,shuffle调优

主要分为开发调优、资源调优、数据倾斜调优、shuffle调优几个部分。 开发调优和资源调优是所有Spark作业都需要注意和遵循的一些基本原则&#xff0c;是高性能Spark作业的基础&#xff1b;数据倾斜调优&#xff0c;主要讲解了一套完整的用来解决Spark作业数据倾斜的解决方案&am…

linux进程间通信:popen函数通过管道与shell通信

函数描述 FILE *popen(const char* command,const char* type) 该函数的执行过程如下&#xff1a; a. 调用pipe创建一个管道&#xff0c;并fork创建一个子进程来执行shell,shell会创建一个子进程来执行commad b. 将父进程的输入输出重定向到管道&#xff0c;建立一个单向的数据…

新的小游戏发布啦。Pop Jungle

丛林爱消除是一款画面清新&#xff0c;效果绚丽的消除类休闲游戏。你只需要选中尽可能多的图块&#xff0c;并消除它们就可以得到高分&#xff0c;并有无限多的关卡等待你去征服。一旦你开始玩儿你将无法停止下来&#xff0c;如果你还是消除星星的粉丝&#xff0c;那你更加不能…

mysql thread safe_Windows环境下完全手工配置Apache、MySQL和PHP(Thread Safe)

happydagui&#xff1a;现在LAMP(Linux、Apache、MySQL、PHP/Perl/Python的简称)已经很流行了。在Windows下也有类似的&#xff0c;比如 WAMP(Apache, MySQL, PHP on Windows)。这篇文章主要是介绍如何在Windows环境下完全手工配置Apache、MySQL和PHP&#xff0c;都是解压后直接…

点滴积累【C#】---检验编号在本表中自动生成,与其他表无关

检验编号在本表中自动生成&#xff0c;与其他表无关 效果&#xff1a; 描述&#xff1a;在本表中自动生成编号&#xff0c;与其他表无关。 调用&#xff1a; 1 protected void Page_Load(object sender, EventArgs e)2 {3 Response.Expires -1;4 …

Alpha冲刺(9/10)

团队信息 队名&#xff1a;爸爸饿了组长博客&#xff1a;here作业博客&#xff1a;here组员情况 组员1&#xff08;组长&#xff09;&#xff1a;王彬 过去两天完成了哪些任务 学习jQuery的AJAX部分的基础知识,对web端如何异步获取服务器信息有了初步认识接下来的计划 & 还…

linux进程通信:pipe实现进程同步

文章目录通过管道同步进程实现代码管道缓冲区设置缓冲区大小总结 &#xff1a;pipe的特点通过管道同步进程 管道自带同步互斥机制&#xff1a; 管道的内核实现&#xff1a;fs/pipe.c &#xff0c;主要通过内核的锁以及等待队列等机制实现 管道的write操作会阻塞进程 当内存缓冲…

(转)MySQL联表查询

资料源于网络 一.内联结、外联结、左联结、右联结的含义及区别在SQL标准中规划的&#xff08;Join&#xff09;联结大致分为下面四种&#xff1a;1.内联结&#xff1a;将两个表中存在联结关系的字段符合联结关系的那些记录形成记录集的联结。2.外联结&#xff1a;分为外左联结和…