原题链接
①. 题目
输入样例
2 3 4 1 5 x 7 6 8
②. 思路
将每一串字符都想象成一个点,已知起点和终点,每一次更新相邻的节点,采用bfs得到到达终点的最短路径,开辟额外空间map来存储对应字符串和对应的次数,bfs将上下左右走判断边界是否符合交换,并且map中不存在这个交换后的字符串,再进行入队列。
③. 学习点
- BFS求最优解
- 一维字符串 转二维矩阵
④. 代码实现
import java.io.*;
import java.util.*;
public class _745_八数码_bfs {
public static void main(String[] args) throws IOException {
/*
* 使用BFS找出最短的距离
* 使用map存储交换后的字符串和交换次数
*/
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] split = bf.readLine().split(" ");
String start="";
//字符串数组转字符串
for (int i = 0; i < split.length; i++) {
start+=split[i];
}
String end="12345678x";
Queue<String> queue=new LinkedList<>();
HashMap<String, Integer> map = new HashMap<String,Integer>();
queue.offer(start);
map.put(start,0);
//上下左右
int[] dx= {0,1,0,-1},dy= {1,0,-1,0};
while(!queue.isEmpty()) {
String t=queue.poll();
//找到直接结束 打印
if(t.equals(end)) {
System.out.println(map.get(t));
return;
}
//找到x的位置
int k=t.indexOf('x');
int x=k/3 ,y=k%3; //将一位坐标转位二维坐标 真的秒
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();
//转为字符数组进行交换
swap(arr,k,a*3+b);
String s = new String(arr);
//如果map中没有这个字符串 入队列 次数+1 否则跳过
if(map.get(s)==null) {
queue.offer(s);
map.put(s,map.get(t)+1);
}
}
}
}
System.out.println(-1);
}
public static void swap(char[] c,int a,int b) {
char temp=c[a];
c[a]=c[b];
c[b]=temp;
}
}