参考了csdn里的一篇文章(leetcode上没找到),他用C++写的, 双向bfs队列搜索。我把C++的代码改成了java,链接:https://blog.csdn.net/qq_45775045/article/details/112548439
实验任务:
1)对九宫重排问题,建立图的启发式搜索求解方法;
2)用A*算法求解九宫重排问题。
实验要求:
3х3九宫棋盘,放置数码为1~8的8个棋子,棋盘中留有一个空格,空格周围的棋子可以移动到空格中,从而改变棋盘的布局。根据给定初始布局和目标布局,移动棋子从初始布局到达目标布局,求解移动步骤并输出。请设计算法,使用合适的搜索策略,在较少的空间和时间代价下找到最短路径。
工具:IDEA jdk1.8
总结:没有成功。。。敲了半天跑不动,无语了。
*****************
能跑了,字符交换后没有赋给原字符串,导致永远返回-1.还有个问题,起点和终点相等也会返回-1.
讲解:BFS:所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。java库的功能写的很多,很方便,但也不够纯粹了,栈
和队列看起来居然很相似。增删就有两种方法。对于这些功能选取合适的即可,其他忽视。
单向BFS太慢了,双向快很多。这里有几个细节,1.起点和终点的visited设置的值不同,这是为了最终前后相遇的判断。要不然无法判断什么时候找到。
2.方向数组,leetcode走几步就看到一堆,算是基本操作3.二维变一维,一维变二维,小技巧4.在赋visited值时用前一个位置的visited的值
代码有注释
代码如下:
import java.util.*;
public class Rearrange{//双向BFS
public static String src_st;//九宫起点状态
public static String des_st;//九宫终点状态
public static Queue<String> queue =new ArrayDeque<>();
/**
* 1.是否访问 2.起点或终点访问
*/
public static Map<String,Integer> visited=new HashMap<>();
public static Map<String,Integer> depth=new HashMap<>(); //搜索深度
public static int dict[][]={{0,-1},{0,1},{1,0},{-1,0}};//方向数组(左右上下遍历)
public static int bfs() {
queue.add(src_st);
queue.add(des_st);
while (!queue.isEmpty()) {
String first = queue.peek();
queue.poll();
int curX = 0, curY = 0;
for (int i = 0; i < first.length(); i++) {//定位空格位置(句点)
if (first.charAt(i) == '.') {
curX = i / 3;
curY = i % 3;
}
}
int newX, newY;
for (int i = 0; i < 4; i++) {//四处逃窜
newX = dict[i][0] + curX;
newY = dict[i][1] + curY;
if (newX >= 0 && newX <= 2 && newY >= 0 && newY <= 2) {//判断边界条件
String new_st = first;
char curtemp = new_st.charAt(curX * 3 + curY);
char newtemp = new_st.charAt(newX * 3 + newY);
new_st= new_st.replace(curtemp, '-');//字符串交换字符
new_st= new_st.replace(newtemp, curtemp);
new_st=new_st.replace('-', newtemp);
if (!visited.containsKey(new_st)) {//没遍历过
visited.put(new_st, visited.get(first));
depth.put(new_st, depth.get(first) + 1);
queue.add(new_st);
} else {
/** 2 4 3
* 遍历过了 1.起点回到起点 2.终点回到终点3.会和
*/
if (visited.get(first) + visited.get(new_st) == 3) {
return depth.get(first) + depth.get(new_st) + 1;
}
}
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入九宫起点字符串:");
src_st=scanner.next();
System.out.println("请输入九宫终点字符串:");
des_st=scanner.next();
visited.put(src_st,1);
visited.put(des_st,2);
depth.put(src_st,0);
depth.put(des_st,0);
int n=bfs();
System.out.println("九宫重排搜索次数:"+"\t"+n);
}
}