结果样例
12345678x
1234567x8
1234x6758
12346x758
12346875x
1234687x5
1234x8765
123x48765
123748x65
1237486x5
12374865x
12374x658
1237x4658
1237546x8
123754x68
123x54768
x23154768
2x3154768
23x154768
23415x768
19
思想
strs数组: 存储出现的字符串
strsh哈希表: 存储字符串出现的下标
pre数组: 存储当前字符串的父节点指针
根据strsh哈希表查找到当前字符串的下标,根据下标在pre数组中查找到父节点下标,根据父节点下标输出strs数组的值。
java 代码
import java.io.*;
import java.util.*;
class Main{
static ArrayDeque<String> q = new ArrayDeque<String>();
static HashMap<String, Integer> d = new HashMap<>();
static int[] dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
static String[] strs = new String[100010];//记录出现过的字符串
static HashMap<String, Integer> strsh = new HashMap<>();//存储当前字符串在数组中的下标
static int[] pre = new int[100010];//记录当前节点的父节点指针
static int idx = 0;
static int res = 0;//记录成功的下标
static int bfs(String start){
q.offer(start);
d.put(start, 0);
strs[idx] = start;//记录当前字符串
strsh.put(start, 0);
pre[idx] = -1;//记录父节点指针,根节点的父节点指针设置为-1
idx++;
String end = "12345678x";
while(q.size() != 0){
String str = q.poll();
int index = strsh.getOrDefault(str, 0);//得到下标作为修改后节点的父节点
int dist = d.get(str);
if(str.equals(end)){
for(int i = res - 1; i != -1; i = pre[i]){//查找祖先节点
System.out.print(strs[i] + "\n");
}
return dist;
}
int k = str.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[] chs = str.toCharArray();
char ch = chs[k];
chs[k] = chs[a * 3 + b];
chs[a * 3 + b] = ch;
String str_new = String.valueOf(chs);
if(!d.containsKey(str_new)){
strs[idx] = str_new;//记录当前字符串
pre[idx] = index;//记录当前字符串的父节点指针
strsh.put(str_new, idx);
idx++;
if(str_new.equals(end)){
res = idx;
}
d.put(str_new, dist + 1);
q.offer(str_new);
}
}
}
}
return -1;
}
public static void main(String[] args)throws Exception{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String str = buf.readLine().replace(" ","");
System.out.print(bfs(str));
}
}