华容道问题求解_详细设计(四)之查找算法2_BFS

2024-03-10 03:44

本文主要是介绍华容道问题求解_详细设计(四)之查找算法2_BFS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(续上篇)
利用BFS查找,会找到最短路径(没有权重的图),这个道理比较简单,这是由于寻找路径的方法都是从起点或者接近起点的位置开始的。查找过程如果画出图来,类似于一圈圈的放大,你可以想想是一个类似圆的渐开线的扫描过程。
前文已经谈到,这个BFS和DFS的主要不同就是对当前参数的保存方法不同,即BFS采用队列保存,DFS采用堆栈保存。因此,将DFS的保存当前参数的方法改成队列就可以实现BFS了。

BFS 核心代码

       internal bool SearchPathBFS(int endHashCode){if (statesObjQueue.Count == 0) return false;//##############################################################//## BFS 代码的改变如下                                        ##//##############################################################var lastState = DequeueState(); //var lastHashCode=   layoutHashCodeStk.Pop();// map it to the current  state MapToCurState(lastState);var curBestSteps = lastState.bestSteps+1;while (gameState.openPieces.Count > 0 && gameState.curOpenIdx < gameState.openPieces.Count)// There are open pieces not moved , move them one by one.{var selOpenPcs = gameState.openPieces[gameState.curOpenIdx];var selPcs = selOpenPcs.piece;var toPcs = selOpenPcs.MoveToPcs;var dirFrom = MoveToPcs(selPcs, toPcs);gameState.selPcs = selPcs;var redundant = RedundantState(gameState);StateShot stateShot = new StateShot(gameState, 0);// record the current best steps stateShot.bestSteps = curBestSteps;//Create the graph data structure AddEdgeToGraph(lastState, stateShot);if (gameState.curOpenIdx < lastState.openPcsArr.Length){gameState.curOpenIdx++;lastState.lastOpenIdx = gameState.curOpenIdx;}if (!redundant.Item1){SearchOpenPieces();stateShot = new StateShot(gameState, 0);stateShot.bestSteps = curBestSteps;//##############################################################//## BFS 代码的改变如下                                       ##//##############################################################         EnqueueState(lastState, stateShot, selPcs, toPcs);//add edge to the grapph and enqueue the current state}// 2024-01-30 Found the least steps with BFS and it runs very fast.// Judge if it succeeds that caocao is at the exit of the board.if (endHashCode==0 && selPcs.type == 4){if (selPcs.hrdPos.X == 2 && selPcs.hrdPos.Y == 4){RefreshLayout();Application.DoEvents();var verTex = GetMyHashCodeV1(gameState);// the layout might not the same that needs to record all of them if (!endVtxLst.Contains(verTex)) endVtxLst.Add(verTex);//MessageBox.Show(string.Format("Success! The best steps is {0},the hash code is {1}", hCodeAndShotShortPathDict[verTex].Item2, verTex));//return false;//debug}}else if (redundant.Item2 == endHashCode){RefreshLayout();Application.DoEvents();var verTex = GetMyHashCodeV1(gameState);// the layout might not the same that needs to record all of them if (!endVtxLst.Contains(verTex)) endVtxLst.Add(verTex);}MapToCurState(lastState); // back the last state and try to moev next open pieces}return true;}

和DFS的代码对比一下就会发现,除了堆栈改成队列之外,代码几乎没有做什么改变。

下面给出 两个主要变化的函数代码
入队代码:

       private void EnqueueState(StateShot source, StateShot dest, Piece selPcs, Piece dstPcs){statesObjQueue.Enqueue(dest);var toHashCode = GetMyHashCode(dest);stateHashCodeLst.Add(toHashCode);int[,] layoutArr = new int[6, 7];Array.Copy(dest.layoutOfIdx, layoutArr, layoutArr.Length);hCodeAndShotDict.Add(toHashCode, (dest.basePcs, selPcs.idx, dstPcs.idx));var frmHashCode = GetMyHashCode(source);AddEdge(frmHashCode, toHashCode, 1);}

出队代码

       private StateShot DequeueState(){var stshot = statesObjQueue.Dequeue();//stateHashCodeStack.Pop();return stshot;}

其中 statesObjQueue 的定义为;

//used to store the game state and the shortest path from last state For BFS search private Queue<StateShot> statesObjQueue= new Queue<StateShot>();

运行之后,就很快找到了最少步数,虽然在过程当中也构建了一个图,但是并没有使用这个图。

结果也比较理想,是一个对称的结果,符合预期。这个原因,我想是因为在BFS 的求解过程当中的每一次探索的步数的基数都是一样的,而路径是不同的,因此也就必然会出现这么一种结果。
运行结果获得30种符合要求的布局,根据对称性,应该是15 中不同的解法。
截图如下:
说明:左面列表数值是该布局对应的Hash值
在这里插入图片描述
在这里插入图片描述
对比上面的布局,发现这是个对称的布局。这些解法中,最少的是81步,最多的是 115步。
其余结果请参考下列视频。另外 “不同解法 ”的含义就是最终的布局不同。

横刀立马最佳结果集


基本功能的探索到此告一段落,后面将对显示和布局设计进行一些尝试。

marasun BJFWDQ
204-03-09

这篇关于华容道问题求解_详细设计(四)之查找算法2_BFS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

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

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

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

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

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

SpringBoot整合liteflow的详细过程

《SpringBoot整合liteflow的详细过程》:本文主要介绍SpringBoot整合liteflow的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...  liteflow 是什么? 能做什么?总之一句话:能帮你规范写代码逻辑 ,编排并解耦业务逻辑,代码

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

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

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出