bfs之八数码

文章目录

    • 八数码
      • 解题思路
      • 图解举例
      • 算法思路
    • 代码
      • CPP代码
      • Java代码

八数码

在一个 3×3的网格中,1∼8这 8个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。

例如:

1 2 3
x 4 6
7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
x 4 6   4 x 6   4 5 6   4 5 6
7 5 8   7 5 8   7 x 8   7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式
输入占一行,将 3×3的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 

则输入为:1 2 3 x 4 6 7 5 8

输出格式
输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 −1。

输入样例
2 3 4 1 5 x 7 6 8
输出样例
19


1、题目的目标

在这里插入图片描述

求最小步数 -> 用BFS

2、移动情况

在这里插入图片描述

移动方式:在这里插入图片描述

转以后:a = x + dx[i], b = y + dy[i].

思想:将每一种情况作为1个节点,目标情况即为终点

从初始状况移动到目标情况 —> 求最短路

3、问题

第一点:怎么表示一种情况使其能作为节点?

第二点:如何记录每一个状态的“距离”(即需要移动的次数)?

第三点:队列怎么定义,dist数组怎么定义?

4、解决方案

将 “3*3矩阵” 转化为 “字符串”

如:

在这里插入图片描述

所以:

队列可以用 queue<string>
//直接存转化后的字符串
dist数组用 unordered_map<string, int>
//将字符串和数字联系在一起,字符串表示状态,数字表示距离

5、矩阵与字符串的转换方式

在这里插入图片描述

解题思路

暴力穷举。穷举出所有给定序列通过交换能得到的新序列,在穷举过程中保存交换次数。

在穷举过程中,如果出现了结果序列,就输出交换次数。

否则不能得到结果序列,输出 -1。

图解举例

在这里插入图片描述

起始状态: 为 1 2 3 x 4 6 7 5 8

交换一次:

  1. x 与上方元素交换得到: x 2 3 1 4 6 7 5 8
  2. x 与右方元素交换得到: 1 2 3 4 x 6 7 5 8
  3. x 与下方元素交换得到: 1 2 3 7 4 6 x 5 8

交换两次得到:

  1. 2 x 3 1 4 6 7 5 8
  2. 1 x 3 4 2 6 7 5 8
  3. 1 2 3 4 6 x 7 5 8
  4. 1 2 3 4 5 6 7 x 8
  5. 1 2 3 7 4 6 5 x 8

交换三次得到:

  1. 2 3 x 1 4 6 7 5 8
  2. 1 2 3 4 5 6 7 8 x

得到了最终结果,输出 3.

算法思路

  1. 用一个队列保存当前获得的序列
  2. 用一个哈希表保存各个序列与对应额交换次数。
  3. 从队列中取出队头这个序列,计算出这个序列通过交换能得到的序列。如果能到得的序列是个新序列(哈希表中没有这个序列),就把这个新序列放入队尾,哈希表中记录新序列对应的交换次数。
  4. 如果在上述过程中得到了结果序列,则输出交换次数,结束。
  5. 如果最终没有得到结果序列。输出-1。

代码

CPP代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <queue>using namespace std;
// 保存各个序列
queue<string> q;
string s;
// 保存序列与对应的交换次数
unordered_map<string, int> h;int main()
{// 输入原始序列for(int i = 1; i <= 9; i++){char c;cin >> c;s += c;}// 保存初始状态h[s] = 0;q.push(s);// 定义上下左右四个交换方向int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};// 依次进行交换while(!q.empty()){// 获得当前序列string t = q.front();q.pop();// 如果是最后结果,输出答案if(t == "12345678x"){cout << h[t] << endl;return 0;}// 找到 x 的位置int pos = t.find('x');// 计算 x 的坐标int a = pos /3 , b = pos % 3 ;// 获取当前序列对应的交换次数int dist = h[t];// 尝试和四个方向的元素进行交换for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];// 判断是否越界if(x >= 0 && x <= 2 && y >= 0 && y <= 2){// 交换swap(t[pos], t[3 * x + y]);// 如果是个新序列,就保存新序列和对应的交换次数if(h.find(t) == h.end()){h[t] = dist + 1;q.push(t);}// 恢复现场,进行下一个方向的交换swap(t[pos], t[3 * x + y]);}}}// 没有得到结果序列,输出-1cout << -1;return 0;
}

Java代码

import java.util.*;
public class Main{public static void swap(char[] arr,int x,int y){char temp = arr[x];arr[x] = arr[y];arr[y] = temp;}public static int bfs(String start ,String end){Map<String,Integer> map = new HashMap<>();// 用来存储每种方式走过的距离Queue<String> q = new LinkedList<>();//队列,用来存储内容q.offer(start);//将初试元素插入到队列的尾部map.put(start,0);//将初始状态的值对应map中value值对应0;表示还没有进行前进;int[] dx = {-1,0,1,0},dy = {0,1,0,-1};//表示前进方向;上下左右//如果队列不是空的继续循环while(!q.isEmpty()){String t = q.poll();//将队头元素返回并抛出int k  = t.indexOf('x');//找到x再String中的下标int x = k / 3 ; int y = k % 3;//然后进行以为数组转化成二维的操作下标操作if(t.equals(end)) return map.get(t); //如果进行过程中跟结束end相同的就提前结束for(int i = 0 ; i < 4 ;  i ++ ){//这里进行四种方案int a = x + dx[i],b = y + dy[i]; if(a >= 0 && a < 3 && b >= 0 && b < 3){ //如果这种情况没有超出边界//将这种情况的字符串转化成字符数组,能够有下标进行交换char[] arr = t.toCharArray(); //然后交换x跟没有超出边界的值进行交换,二维转成一维下标x*3+y;swap(arr, k, a * 3 + b);//然后将字符数组转化成字符串String str = new String(arr);if(map.get(str) == null){ //如果这种情况对应的value值是null,说明还没有走过map.put(str,map.get(t) + 1);//然后将这种情况对应进行上一步的距离加上1q.offer(str);//然后将新的情况插入到队尾中}}//思路://比如走到距离为2即第二步时候,上下左右四种情况都可行的情况下,将每一中情况都//插入到队列尾部,然后queue[] = {2[1],2[1],2[1],2[1],3[1],3[1],3[2],3[4]};//队列会执行从前面开始2执行完之后可能会有3种情况往队列尾插入,//然后这样依次每一层进行搜索遍历//因为步数小的都会先插入到队列中,队列原则"先进先出"原则,所以肯定会把所有的//第二步执行完之后才会执行前面第二步执行过程中产生的三步,然后一直执行到最后第n步}}return -1; //如果执行完之后没有结果,那么返回-1;}public static void main(String[] args){Scanner scan = new Scanner(System.in);String start = "";for(int i = 0 ; i < 9 ; i ++ ){String s = scan.next();start += s;}String end = "12345678x";System.out.println(bfs(start,end));}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/7962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Oracle】Linux x86-64 安装Oracle 23AI指南

本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 前言 在信息技术日新月异的今天&#xff0c;企业级数据库系统扮演着数据管理与业务支撑的核心角色。Oracle数据库&#xff0c;作为全球…

IAP15W4K61S4单片机EEPROM读写程序

/*-------------关闭IAP----------------*/ void IapIdle() { IAP_CONTR 0; //关闭IAP功能 IAP_CMD 0; //清除命令寄存器 IAP_TRIG 0; …

专业软件测试会议

全国软件测试会议&#xff1a;这是一个系列性的专业会议&#xff0c;由中国的学术机构或专业组织主办&#xff0c;例如中国计算机学会的容错计算专业委员会。此会议自2005年起开始举办&#xff0c;历届会议地点包括北京、昆明和武汉等地。会议内容覆盖软件测试理论、实践、工具…

跟TED演讲学英文:4 pillars of college success in science by Freeman Hrabowski

4 pillars of college success in science Link: https://www.ted.com/talks/freeman_hrabowski_4_pillars_of_college_success_in_science Speaker: Freeman Hrabowski Date: February 2013 文章目录 4 pillars of college success in scienceIntroductionVocabularyTranscr…

uniapp打包的程序在Xcode中运行到模拟器报错的解决方法

uniapp打包的程序在Xcode中运行到模拟器报错的解决方法 问题描述&#xff1a; Building for iOS-simulator, but linking in object file (/Users/hori/Documents/SDK/SDK/Libs/DCUniRecord.framework/DCUniRecord[arm64][3](PGRecord.o)) built for iOS Linker command fail…

Day 25 数据库查询

数据库查询 一&#xff1a;基本查询 1.简介 ​ 单表查询 ​ 简单查询 ​ 通过条件查询 ​ 查询排序 ​ 限制查询记录数 ​ 使用集合函数查询 ​ 分组查询 ​ 使用正则表达式查询 2.案例 创建案例所需表&#xff1a;company.employee5 雇员编号 id int雇…

ISIS的工作原理

1.邻居关系建立 &#xff08;1&#xff09;IS-IS领接关系建立原则 1、通过将以太网接口模拟成点到点接口&#xff0c;可以建立点到点链路邻接关系。 2、当链路两端IS-IS接口的地址不在同一网段时&#xff0c;如果配置接口对接收的Hello报文不作IP地址检查&#xff0c;也可以建…

【AI】Tavily

Tavily是一个为人工智能代理&#xff08;如大型语言模型&#xff0c;LLMs&#xff09;和检索增强生成&#xff08;RAG&#xff09;应用优化的搜索引擎。它旨在提供高效、快速和持久的搜索结果。Tavily Search API 允许人工智能开发人员轻松地将他们的应用程序与实时在线信息集成…

深入理解MySQL的Purge机制

在MySQL中&#xff0c;尤其是在使用InnoDB存储引擎时&#xff0c;Purge机制起着至关重要的作用。它主要负责清理那些因为早期的版本或删除操作而不再需要的数据行版本。本文将详细介绍MySQL中的Purge机制&#xff0c;包括其作用、工作原理、如何配置以及优化步骤。 1. Purge机…

网络基础(1)详解

目录 1.计算机网络背景 2.网络协议 3.网络中的地址管理 1.计算机网络背景 1.1 网络发展 (1)计算机从独立模式到网络互联(多态计算机连接共享数据)再到局域网LAN(通过交换机和路由器连接)接着是广域网WAN 1.2 协议 协议就是双方的一种约定. 为什么要有协议? 因为在数据长距…

LeetCode 面试经典150题 252.会议室

题目&#xff1a;给定一个会议时间安排的数组 intervals &#xff0c;每个会议时间都会包括开始和结束的时间 intervals[i] [starti, endi] &#xff0c;请你判断一个人是否能够参加这里面的全部会议。 思路&#xff1a;因为一个人在同一时刻只能参加一个会议&#xff0c;因此…

Unit5

Unit5 1. main&#xff0c;man 停留 maintain maintenance remain remaining remainder permanent 2. place 地方&#xff1b;放置 place placement plaza palace replace replace A with B replacement irreplaceable birthplace workplace marketplace misplace mis…

一起刷C语言菜鸟教程100题(15-26含解析)

五一过的好快&#xff0c;五天假期说没就没&#xff0c;因为一些事情耽搁到现在&#xff0c;不过还是要继续学习的&#xff0c;之后就照常更新&#xff0c;先说一下&#xff0c;这个100题是菜鸟教程里面的&#xff0c;但是有一些题&#xff0c;我加入了自己的理解&#xff0c;甚…

网络1--通信过程的理解

1.封装与解包 通信的过程就是不断的封装和解包的过程 封装即就是按照“应用”“传输” “网络” “链路” 层&#xff0c;封装给每一层都加上相应的包头&#xff08;每一层都有协议&#xff0c;&#xff09;解包就是接受到的包文被一层层去掉相对应的包头。 任何一层的协议都…

JavaScript解决精度问题-math.js-使用入门

JavaScript精度失真案例 0.1+0.2 结果是:0.300000000000000041-0.9 结果是:0.099999999999999984.10*100 结果是:409.999999999999946.10/0.1 结果是:60.99999999999999大数计算 9007199254740992+1 结果是9007199254740992 JavaScript 浮点数运算结果不对,因浮点数的存储…

ResNet神经网络搭建

一、定义残差结构 BasicBlock 18层、34层网络对应的残差结构 浅层网络主线由两个3x3的卷积层链接&#xff0c;相加后通过relu激活函数输出。还有一个shortcut捷径 参数解释 expansion 1 &#xff1a; 判断对应主分支的残差结构有无变化 downsampleNone &#xff1a; 下…

Minio(官方docker版)容器部署时区问题研究记录

文章目录 感慨&概述补充&#xff1a;MINIO_REGION和容器时间的关系 问题一&#xff1a;minio容器和本地容器时间不一致问题说明原因探究解决方法结果验证 问题二&#xff1a;minio修改时间和本地查询结果不一致具体问题原因探究解决办法时间转化工具类调用测试和验证上传文…

Unit6

Unit6 1. val 强壮 valid invalid validate invalidate prevail prevailing prevalent 2. pri 主要的 prime Prime Minister premier primary primary school prior prior to sth prioritize priority principle principal prince princess 3. nov 新 news newspap…

thinkphp5 中路由常见的使用方法

在ThinkPHP 5中&#xff0c;路由的常见使用方法主要包括以下几个方面&#xff1a; 基本路由配置&#xff1a; 你可以通过修改config目录下面的route.php文件来配置路由规则。例如&#xff0c;使用Route::get或Route::post等方法定义不同的HTTP请求类型的路由。 use think\Route…

stm32芯片外设

STM32 F1系列微控制器是ST公司推出的一系列基于ARM Cortex-M3内核的微控制器。这一系列微控制器拥有丰富的外设资源&#xff0c;包括但不限于&#xff1a; ADC&#xff08;模数转换器&#xff09;&#xff1a;用于将模拟信号转换为数字信号&#xff0c;通常用于传感器数据的读取…