八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始状态转变成目标状态的移动棋子步数最少的移动步骤。

一开始也是两眼一抹黑,连八数码是什么都不知道,经过度娘得到如上结果。那该如何实现呢?如果移动数字的话,8个数字,每次移动有4种选择,那就是32个种移动方案。那移动空格就只有4种选择,一下子清楚了很多。至于存储方案当然是数组了,交换起来多方便,是吧?

实现方式呢?最初实验要求使用回溯算法解决,什么,回溯?!那不是和深度优先一样吗?无脑走找结果?算了,先试试吧。

import numpy as np

#返回两个数组对应位置相同值的个数

def calc(state1):

b = np.array([[1, 2, 3], [8, 0, 4], [7, 6, 5]])

postion = np.where(state1 == b)

return len(state1[postion])

#打印八数码

def showInfo(a):

for i in range(3):

for j in range(3):

print(a[i, j], end=' ')

print("\n")

print('->')

directions = ['up', 'down', 'left', 'right']

def SubStates(state):

subStates = []

row, col = np.where(state==0)

for direction in directions:

if 'left' == direction and col > 0:

s = state.copy()

s[row, col],s[row, col - 1] = s[row, col - 1],s[row, col]

subStates.append(s)

if 'up' == direction and row > 0:

s = state.copy()

s[row, col],s[row - 1, col] = s[row - 1, col],s[row, col]

subStates.append(s)

if 'down' == direction and row < 2:

s = state.copy()

s[row, col],s[row + 1, col] = s[row + 1, col],s[row, col]

subStates.append(s)

if 'right' == direction and col < 2:

s = state.copy()

s[row, col],s[row, col + 1] = s[row, col + 1],s[row, col]

subStates.append(s)

return subStates

def DFS(first):

stack = []

stack.append(first)

count = -1

while stack:

count += 1

node = stack.pop()

showInfo(node)

if calc(node) == 9:

return True,count

s = SubStates(node)

#res = sorted(s, key=calc)

for x in res:

stack.append(x)

#主函数

def main():

start = np.array([[0, 1, 3], [8, 2, 4], [7, 6, 5]])

#start = np.array([[2, 8, 3], [1, 0, 4], [7, 6, 5]])

res,count = DFS(start)

if res:

print('经过%d次变换结束' %count)

if __name__ == '__main__':

main()

用迭代方式很容易的写出了深度优先算法,可是貌似跑不出结果。。。what a fuck,什么鬼?遂找了个只移动两次的,运行,还是不行。随机压栈太疯狂了,加点约束吧。每次找和最终结果最相似的出栈应该可以。(这里说一下为了防止无限次循环,用宽度优先搜素比较合适,只需把pop()改成pop(0),如果用到排序的话那就要按相似度由高到低排列了)嗯,加上这句res = sorted(s, key=calc),压栈前按相似度由低到高做一次排序。移动两次的果然跑出来了,可是移动多次的还是不行。

得,再想办法吧。做一个界限函数,用八数码迭代出来的层数加上相似度来搜索。这个值在一定限度才入栈,否则舍弃。

这里我将节点封装成一个类来实现。

import numpy as np

class eightPuzzle(object):

directions = ['up', 'down', 'left', 'right']

max = 7

def __init__(self,arr,cost=0,parent=None):

self.arr = arr

self.cost = cost

self.parent = parent

def getCost(self):

return self.cost

# 返回两个数组对应位置相同值的个数

def calc(self,state):

final = np.array([[1, 2, 3], [8, 0, 4], [7, 6, 5]])

postion = np.where(state.arr == final)

return len(state.arr[postion])

# 打印八数码

def showInfo(self):

for i in range(3):

for j in range(3):

print(self.arr[i, j], end=' ')

print("\n")

print('->')

def calc2(self, state1, stop):

for x in stop:

postion = np.where(state1.arr == x.arr)

if len(state1.arr[postion]) == 9:

return True

return False

def SubStates(self):

subStates = []

row, col = np.where(self.arr==0)

for direction in self.directions:

if 'left' == direction and col > 0:

s = self.arr.copy()

s[row, col],s[row, col - 1] = s[row, col - 1],s[row, col]

new = eightPuzzle(s,self.cost+1,self)

subStates.append(new)

if 'up' == direction and row > 0:

s = self.arr.copy()

s[row, col],s[row - 1, col] = s[row - 1, col],s[row, col]

new = eightPuzzle(s, self.cost + 1,self)

subStates.append(new)

if 'down' == direction and row < 2:

s = self.arr.copy()

s[row, col],s[row + 1, col] = s[row + 1, col],s[row, col]

new = eightPuzzle(s, self.cost + 1,self)

subStates.append(new)

if 'right' == direction and col < 2:

s = self.arr.copy()

s[row, col],s[row, col + 1] = s[row, col + 1],s[row, col]

new = eightPuzzle(s, self.cost + 1,self)

subStates.append(new)

return subStates

def DFS(self):

stack = []

stop = []

stack.append(self)

count = -1

while True:

if not stack:

return False,count,node

count += 1

#stack = sorted(stack, key=self.calc)

node = stack.pop()

stop.append(node)

node.showInfo()

if self.calc(node) == 9:

return True,count,node

s = node.SubStates()

if s:

res = sorted(s, key=self.calc)

else:

continue

for x in res:

if (x.cost + 9 - self.calc(x))< eightPuzzle.max:

if self.calc2(x,stop):

continue

stack.append(x)

def showInfo(result):

for node in result:

for i in range(3):

for j in range(3):

print(node.arr[i, j], end=' ')

print('\n')

print('->')

#主函数

def main():

#start = np.array([[0, 1, 3], [8, 2, 4], [7, 6, 5]])

start = np.array([[2, 8, 3], [1, 0, 4], [7, 6, 5]])

p = eightPuzzle(start)

res,count,node = p.DFS()

result = []

if res:

print('经过%d次变换结束' %count)

while node:

result.append(node)

node = node.parent

result.reverse()

showInfo(result)

else:

print('规定范围内未找到合适路径,可增大界值')

if __name__ == '__main__':

main()

这次经过七次搜索得到了最终答案。

这时候发现输出很有意思,会出现初始状态。因此在深度搜索的过程中加了一个stop表,用来存储已经出栈的元素,每次入栈的时候查看若已经存在则扔掉。此时运行6次出现答案。

结束。

python解决八数码问题_python解决八数码问题相关推荐

  1. python idea控制台中文乱码_python 解决cv2绘制中文乱码问题

    python 解决cv2绘制中文乱码问题 因为使用cv2.putText() 只能显示英文字符,中文会出现乱码问题, 因此使用PIL在图片上绘制添加中文,可以指定字体文件. 大体思路: OpenCV图 ...

  2. python单行动态刷新不了_python 解决tqdm模块不能单行显示的问题

    python 解决tqdm模块不能单行显示的问题 OS: Windows 10 IDE: Anaconda Spyder (Python3.6) 代码如下: from tqdm import tqdm ...

  3. python汉字的unicode编码_python解决汉字编码问题:Unicode Decode Error

    前言 最近由于项目需要,需要读取一个含有中文的txt文档,完了还要保存文件.文档之前是由base64编码,导致所有汉字读取显示乱码.项目组把base64废弃之后,先后出现两个错误: ascii cod ...

  4. python中小球落地问题_Python解决抛小球问题 求小球下落经历的距离之和示例

    本文实例讲述了Python解决抛小球问题 求小球下落经历的距离之和.分享给大家供大家参考,具体如下: 问题: 小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他 ...

  5. python序列类型举例说明_Python(第八课,序列类型)

    引言: 我们之前学过整数,浮点数,字符串,今天带来的更具有包容性. 今天带来的是高级数据类型,包括列表,元组,集合和字典.根据他们特性不同,可以分为序列类型,集合类型,键值类型. 一,序列类型 1.1 ...

  6. python替换文本换行符_python解决replace(“/n“,““)无法替换换行符

    先看原数据,一直在想办法清除 "\n"和"/"这两个符号. # 从提取出的几列来看,还有些细节需要再洗洗:例如为了统计和美观需要,"\n"和 ...

  7. python的简单代码五角星_Python第八课 绘制五角星1.0

    Turtle库使用方法: import turtle turtle.函数() Turtle 库的使用规则: 1)必须在使用前引入turtle库. 2)在使用过程中通过turtle.函数()来调用相关的 ...

  8. 八皇后问题python_python八皇后问题的解决方法

    本文为大家分享了python八皇后问题的解决方法,供大家参考,具体内容如下 题目: 给定一个 N*N 正方形棋盘,在上面放置 N个棋子,又叫皇后,使每两个棋子都不在同一条横线上.竖线上.斜线上.一般我 ...

  9. 【Vue2.0】—解决页面闪烁的问题(八)

    [Vue2.0]-解决页面闪烁的问题(八) v-cloak指令(没有值) 1.本质上是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性 2. 使用css配合v-cloak可解决网 ...

  10. JVM出现OOM的八种原因及解决办法

    本文源自转载:JVM出现OOM的八种原因及解决办法 目录 一.堆溢出 1.1 原因 1.2解决方法 二.永久代/元空间溢出 2.1 原因 2.2 解决方法 三.GC overhead limit ex ...

最新文章

  1. iOS - Regex 正则表达式
  2. 2017 年初、阿里、腾讯、百度、华为、京东、搜狗和滴滴面试题汇集(更新篇)...
  3. halcon知识:【2】二维码原理
  4. linux——awk 报告生成器
  5. BZOJ 4823 Luogu P3756 [CQOI2017]老C的方块 (网络流、最小割)
  6. 非域环境下使用证书部署数据库(SqlServer2008R2)镜像
  7. udt java_Java DB中的Java用户定义类型(UDT)
  8. Hapoxy+keepalived实现双主高可用负载均衡
  9. 草莓甜品海报设计,甜出画面,受得住诱惑么?
  10. orange实现逻辑回归_逻辑回归模型
  11. java版我的世界光追,老瓶装新酒 光追版《我的世界》将至你心动了吗
  12. html图片轮播_前端轮播图怎么做?JavaScript来帮你轻松搞定
  13. PAIP.利用SyncML协议来同步备份手机短信联系人.txt
  14. VPP-20.09版本安装教程(联网版)
  15. poi处理office转pdf
  16. MS5611气压计数据采集(模拟IIC)/温度采集/相对高度求解
  17. Python常用字符编码
  18. 3D立方体图片切换动画
  19. pic12f1823单片机入门_PIC单片机新手快速入门
  20. spring 定义自己的标签 学习

热门文章

  1. ORACLE SQL优化大全
  2. 模板引擎template.js
  3. oracle odac 配置,.Net項目中通過ODAC方式鏈接Oracle數據庫相關配置
  4. Mysql 使用Maxscale读写分离,负载均衡
  5. linux/android中aplay/arecord用法以及命令
  6. 2021年T电梯修理免费试题及T电梯修理试题及解析
  7. Ubuntu16.04 安装 卸载 pip
  8. 实验报告(LCS算法和背包算法)
  9. 云服务综合解决方案——云桌面
  10. S7-200SMART PLC与V20变频器MODBUS通讯示例程序