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…

ISIS的工作原理

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

网络基础(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;因此…

一起刷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 浮点数运算结果不对,因浮点数的存储…

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

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

高级数据结构与算法习题(9)

一、判断题 1、Let S be the set of activities in Activity Selection Problem. Then the earliest finish activity am​ must be included in all the maximum-size subset of mutually compatible activities of S. T F 解析:F。设S是活动选择问题中的一…

flutter开发实战-webview_flutter 4.x版本使用

flutter开发实战-webview_flutter 4.x版本使用 在之前使用的webview_flutter版本是3.x的&#xff0c;升级到4.x后&#xff0c;使用方式有所变化。 一、webview_flutter 在工程的pubspec.yaml中引入插件 webview_flutter: ^4.4.2二、使用webview_flutter 在4.x版本中&#…

JAVA语言开发的(智慧校园系统源码)智慧校园的痛点、智慧校园的安全应用、智慧校园解决方案

一、智慧校园的痛点 1、信息孤岛问题&#xff1a;由于校园内各部门或系统独立开发&#xff0c;缺乏统一规划和标准&#xff0c;导致数据无法有效整合和共享&#xff0c;形成了信息孤岛。 2、技术更新与运维挑战&#xff1a;智慧校园的建设依赖于前沿的信息技术&#xff0c;如云…

15【PS作图】像素画地图绘制

绘制视角 绘制地图的时候&#xff0c;有的人会习惯把要绘制的 房子、车子、围栏 小物件先画好&#xff0c;然后安放在地图上 但这样绘制出的各种物件之间&#xff0c;会缺乏凝聚力 既然物品都是人构造出的&#xff0c;不如以人的视角去一步步丰富地图&#xff1b; 比如下图…

关于c++ 中 string s { ‘a‘ , ‘b‘ , ‘c‘ , ‘d‘ } 的方式的构造过程

&#xff08;1&#xff09;这样的构造方式不常见&#xff0c;但也确实 STL 库提供了这样的构造函数 &#xff08;2&#xff09;以反汇编分析这行代码 &#xff08;3&#xff09;谢谢阅读

【数据结构与算法】力扣 239. 滑动窗口最大值

题干描述 给你一个整数数组 nums&#xff0c;有一个大小为 k **的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a; nums [1,3,-1,-3,5,3…

嵌入式开发常见概念简介

目录 0. 《STM32单片机自学教程》专栏总纲 API Handle(句柄) 0. 《STM32单片机自学教程》专栏总纲 本文作为专栏《STM32单片机自学教程》专栏其中的一部分&#xff0c;返回专栏总纲&#xff0c;阅读所有文章,点击Link: STM32单片机自学教程-[目录总纲]_stm32 学习-CSD…

每日OJ题_贪心算法三⑤_力扣134. 加油站

目录 力扣134. 加油站 解析代码 力扣134. 加油站 134. 加油站 难度 中等 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一…