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

相关文章

Nginx错误拦截转发 error_page的问题解决

《Nginx错误拦截转发error_page的问题解决》Nginx通过配置错误页面和请求处理机制,可以在请求失败时展示自定义错误页面,提升用户体验,下面就来介绍一下Nginx错误拦截转发error_... 目录1. 准备自定义错误页面2. 配置 Nginx 错误页面基础配置示例:3. 关键配置说明4. 生效

python版本切换工具pyenv的安装及用法

《python版本切换工具pyenv的安装及用法》Pyenv是管理Python版本的最佳工具之一,特别适合开发者和需要切换多个Python版本的用户,:本文主要介绍python版本切换工具pyen... 目录Pyenv 是什么?安装 Pyenv(MACOS)使用 Homebrew:配置 shell(zsh

Python自动化提取多个Word文档的文本

《Python自动化提取多个Word文档的文本》在日常工作和学习中,我们经常需要处理大量的Word文档,本文将深入探讨如何利用Python批量提取Word文档中的文本内容,帮助你解放生产力,感兴趣的小... 目录为什么需要批量提取Word文档文本批量提取Word文本的核心技术与工具安装 Spire.Doc

Python中Request的安装以及简单的使用方法图文教程

《Python中Request的安装以及简单的使用方法图文教程》python里的request库经常被用于进行网络爬虫,想要学习网络爬虫的同学必须得安装request这个第三方库,:本文主要介绍P... 目录1.Requests 安装cmd 窗口安装为pycharm安装在pycharm设置中为项目安装req

Python容器转换与共有函数举例详解

《Python容器转换与共有函数举例详解》Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面:本文主要介绍Python容器转换与共有函数的相关资料,... 目录python容器转换与共有函数详解一、容器类型概览二、容器类型转换1. 基本容器转换2. 高级转换示

使用Python将PDF表格自动提取并写入Word文档表格

《使用Python将PDF表格自动提取并写入Word文档表格》在实际办公与数据处理场景中,PDF文件里的表格往往无法直接复制到Word中,本文将介绍如何使用Python从PDF文件中提取表格数据,并将... 目录引言1. 加载 PDF 文件并准备 Word 文档2. 提取 PDF 表格并创建 Word 表格

使用Python实现局域网远程监控电脑屏幕的方法

《使用Python实现局域网远程监控电脑屏幕的方法》文章介绍了两种使用Python在局域网内实现远程监控电脑屏幕的方法,方法一使用mss和socket,方法二使用PyAutoGUI和Flask,每种方... 目录方法一:使用mss和socket实现屏幕共享服务端(被监控端)客户端(监控端)方法二:使用PyA

Python列表的创建与删除的操作指南

《Python列表的创建与删除的操作指南》列表(list)是Python中最常用、最灵活的内置数据结构之一,它支持动态扩容、混合类型、嵌套结构,几乎无处不在,但你真的会创建和删除列表吗,本文给大家介绍... 目录一、前言二、列表的创建方式1. 字面量语法(最常用)2. 使用list()构造器3. 列表推导式

Python使用Matplotlib和Seaborn绘制常用图表的技巧

《Python使用Matplotlib和Seaborn绘制常用图表的技巧》Python作为数据科学领域的明星语言,拥有强大且丰富的可视化库,其中最著名的莫过于Matplotlib和Seaborn,本篇... 目录1. 引言:数据可视化的力量2. 前置知识与环境准备2.1. 必备知识2.2. 安装所需库2.3

Python数据验证神器Pydantic库的使用和实践中的避坑指南

《Python数据验证神器Pydantic库的使用和实践中的避坑指南》Pydantic是一个用于数据验证和设置的库,可以显著简化API接口开发,文章通过一个实际案例,展示了Pydantic如何在生产环... 目录1️⃣ 崩溃时刻:当你的API接口又双叒崩了!2️⃣ 神兵天降:3行代码解决验证难题3️⃣ 深度