3*3拼图复原 (8数码问题) 每步穷举搜索(BFS广度搜索) Python解法

2023-11-11 19:30

本文主要是介绍3*3拼图复原 (8数码问题) 每步穷举搜索(BFS广度搜索) Python解法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近有同学 让我复原一个拼图 就想用代码解决 写了个 python的解决方案.
原始图片
原始输入图片
在这里插入图片描述
复原完成图片

解题思路就是 遍历每个可能步数 如下图的遍历方式
在这里插入图片描述
想法就是用 for 遍历.
难点1.如果要记住所有遍历过程, 拼图越来越大的话,会爆内存, 需要占用的储存空间太大了.
解决方案1.就是每步都只记住上一步得出的 所有输出,在之前的输出就都忘记掉.然后输出本步所有的(拼图形状,空白块位置,本次移动方向), 作为下一次迭代的输入

难点2. 如果每次都丢掉所有数据,最后只能得出 拼图是否可以完成,在多少步内完成的输出结果,并不能显示出 如何移动方块使得拼图复原的所有步骤.
解决方案2. 在函数内加入一个空列表, 列表每次记录这次行走的方向.
也就是 最终还是要有一个列表记录所有走法的全部数据.并且给每个数据特殊的标识, 使得系统可以识别出这个数据是在第几步.
(当然也可以 上次方向+本次方向 生成一个新的单一识别化数据, 然后这个数据与下次 方向又生成一个单一识别化数据, 这样每次用完上次数据 就可以丢弃了,也节省了内存, 不过这个方法我暂时没有去实现, 下面会给出 实现的逻辑思维,)

#  将 行走方向 数字化
字典 = {'上':-3, '下':3, '左':-1, '右':1}
翻译字典 = {-3:'上', 3:'下', -1:'左', 1:'右'}

记录出的所有数据

for 遍历 in randomlist_new:#选定随机走位, 但不得走回上次位置count2 += 1if 遍历 >0:每步所有数据1.append(遍历+count*10)else:每步所有数据1.append(遍历-count*10)

重点 1.每做一次遍历 也就是每走记录 , 让count数+1, 然后让count+上本次步数,就得出了特征化的新数据如下图所示
在这里插入图片描述
个位数和正负号表示这次所走的方向, 个位数之前的数字就代表是第几步.
比如 81 也就是 第8步的策略,走了1 ,1也就是走了右.
最后再将步数数据 翻译成中文即可
PS: 当然有想法的兄弟们 可以不用累计记录这么多冗杂数据. 每次只用上次 数据 + 本次 数据 ,输出新数据. 这样是最简化也是 最优化的方法, 非常省内存! 比如 上下左右 使用 1234 标记.
然后比如 一个步数记录应该是 [上左左下右右]
第一步输出: 1
第二步输出: 1+3 = 31
第三步输出: 31 + 3 = 331
第4步输出: 331 + 2 = 2331
第5步输出: 2331+ 4 = 42331
第6步输出: 42331 + 4 = 442331

很明显 只要通过 最后 第六步的一个数据 442331 我们就可以得出 以前所有的步数 内容,
输入 也仅需要 第五步的结果输入 和 本部生成的步数

不过我这个没有在我的代码里实现, 有兴趣的兄弟们可以自己实现一下.

2.我比较笨 想来想去, 只想出了一个拼图逻辑, 也就是 禁止拼图,回走上一步, 其他所有可能都需要遍历

以下贴出 所有代码

import numpy as np
def 交换位置(数据汇总,完成迷宫):   #移动一个拼图方块,本质上就是两个方块交换位置 所以这是一个 N次交换方块位置的 实质
# 给出两个输入  数据汇总就是 1.上步所有可能的迷宫形状 2.所有迷宫形状下 空白格所在位置 3.所有上次行走的方向  
# 完成迷宫 就是 最后需要 打到的迷宫形状 一般就是  123456789是否完成 = 0上步数据 = 数据汇总数据汇总 = []每步所有数据1 = []count = 0count2 = -1for 初始迷宫,初始位置,前位置随机数 in 上步数据:count += 1if 初始位置==1:  # 手写给出 每个位置方块可以走的情况, 比如四个角 明显只有两个走法可以走randomlist = np.array([字典['右'], 字典['下']])if 初始位置==2:randomlist = np.array([字典['右'], 字典['左'], 字典['下']])if 初始位置==3:randomlist = np.array([字典['左'], 字典['下']])if 初始位置==4:randomlist = np.array([字典['右'], 字典['上'], 字典['下']])   if 初始位置==5:randomlist = np.array([字典['右'], 字典['下'], 字典['上'], 字典['左']])if 初始位置==6:randomlist = np.array([字典['上'], 字典['左'], 字典['下']])if 初始位置==7:randomlist = np.array([字典['右'], 字典['上']])if 初始位置==8:randomlist = np.array([字典['右'], 字典['左'], 字典['上']])if 初始位置==9:randomlist = np.array([字典['左'], 字典['上']])randomlist_new = np.setdiff1d(randomlist, 前位置随机数*-1) #给出随机走位所有可能, 但不得走回上次位置  ,也就是将上述 randomlist去除上次走路方向的元素初始位置 = 初始位置-1 #我的输入是123456789大家容易看懂  但需要转换为python 表达方式 012 345678for 遍历 in randomlist_new:count2 += 1if 遍历 >0:  #将每步特征化,将每步走的方向 放入到列表中每步所有数据1.append(遍历+count*10)else:每步所有数据1.append(遍历-count*10)初始迷宫_copy = 初始迷宫.copy()初始迷宫_copy[初始位置], 初始迷宫_copy[初始位置+遍历] = 初始迷宫_copy[初始位置+遍历], 初始迷宫_copy[初始位置]  #完成走位,得到新迷宫图  也就是交换两个元素位置数据汇总.append((初始迷宫_copy, 初始位置+遍历+1, 遍历))判断 = (初始迷宫_copy==完成迷宫)  #判断得到的新迷宫 是不是 需要完成的迷宫if 判断.all() :count2合集.append(count2)是否完成 = 1print('''完成拼图:{}'''.format(count2))break步数记录.append(每步所有数据1)return(数据汇总, 是否完成, count2合集)
count2合集 = []
字典 = {'上':-3, '下':3, '左':-1, '右':1}
翻译字典 = {-3:'上', 3:'下', -1:'左', 1:'右'}
完成迷宫1  = np.array([1,2,3,4,5,6,7,8,9])            # 最终迷宫形状
数据汇总1  = [[np.array([6,3,8,1,4,5,2,7,9]), 9, 0]]  # 初始迷宫形状  空白格位置  以及 前置步数操作(第一步也就是没有前置操作.设为0)
步数记录 = []
for i in range(21):  #重点 我的函数是每调用一次走一步, 所以我们需要 用for函数 指定拼图所要走的步数, 我们假定一开始 不知道多少步可以复原迷宫 可以 range里面输入100,也就是要求100步内完成迷宫,当然我们在看到有步数 输出的时候就可以暂停运行, 降低步数.  这里我给的数据是 必须在21步内完成.最终输出就是20步之内就可以完成数据汇总1, 是否完成,完成路线 = 交换位置(数据汇总1,完成迷宫1)ans1 = []     #以下代码是对 输出的 每步步数回溯翻译成 中文的行走方向, 这个我个人觉得也是重点.
for a in 完成路线:test = []ans2 = []for i in range(20):test.append(a)a = np.abs(步数记录[-1*(i+1)][a])//10 - 1for i,j in enumerate(test[::-1]):if 步数记录[i][j] < 0:ans2.append(翻译字典[np.abs(步数记录[i][j])%10*-1])else:ans2.append(翻译字典[np.abs(步数记录[i][j])%10])ans1.append(ans2)
for i in ans1:print(i)

展示输出
在这里插入图片描述
也就是 在限定小于等于20步之内完成拼图,只有两种走法
分别是571号, 6247号 策略
翻译成如下 两个列表的中文走法形式

这篇关于3*3拼图复原 (8数码问题) 每步穷举搜索(BFS广度搜索) Python解法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/392339

相关文章

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

python常用的正则表达式及作用

《python常用的正则表达式及作用》正则表达式是处理字符串的强大工具,Python通过re模块提供正则表达式支持,本文给大家介绍python常用的正则表达式及作用详解,感兴趣的朋友跟随小编一起看看吧... 目录python常用正则表达式及作用基本匹配模式常用正则表达式示例常用量词边界匹配分组和捕获常用re