题目:
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
思路:
建造一个picture类,里面用于存放每一步的状态,当前"."所在的位置,已经当前是第几步,之后使用linkedlist存放每一次的状态,当结束一个状态之后判断是否与目标状态相同,如果相同的话那么就是这个状态,输出结果。把那个”.“当做一个人,就类似于走迷宫。
注意点:
1、中间每一次都要记录状态,我使用了String进行记录,将当前的数组遍历一下转换成为一个String,如果数组唯一,状态可以定也是唯一的。
2、要知道bfs是一个扩散式的搜索,当从一个节点搜索的时候会搜索出其余方向的几种状态,但是当让一个picture对象出队的时候,记住每一次子对象都是需要使用父对象修改,也就是在父对象基础上进行修改,所以我在中间增加了一次的复制操作。
3、最后使用一个arraylist用于记录每一次出现的状态,如果当前这个状态已经出现过了,那么下一次就不需要在对他进行入队了,避免重复计算。
**总结:**一道题目如果是求最短次数,最短的状态变换,求到达状态,基本上你就是往bfs上面想。
代码:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
public class 九宫重排 {
public static String startString,endString;
public static String shu[][] = new String[3][3];
public static LinkedList<picture> list = new LinkedList<>();
public static ArrayList<String> arrayList = new ArrayList<>();//用于判断之前是够走到过这种状态,如果有的话就不不走了。
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
startString =input.next();
endString = input.next();
int t =0;
for (int i = 0; i < startString.length(); i++) {
shu[t/3][t%3] = startString.substring(i,i+1);
t++;
} //用于将输入的数据转换成为数组
bfs();
}
public static void bfs() {
int p = startString.indexOf(".")/3;//用于确定点的位置
int q = startString.indexOf(".")%3;
list.addLast(new picture(p, q, 0, startString));
arrayList.add(startString);
while(!list.isEmpty()) {
picture temporacy = list.removeFirst();//一定是要从开头移除,队列,先进先出,从尾部插入,从头部出来
int next [][] = {{0,1},{1,0},{0,-1},{-1,0}};//分别模拟四个方向右边,下边,左边,上边
int tx,ty;
for (int i = 0; i < next.length; i++) {
tx =temporacy.x + next[i][0];
ty =temporacy.y+next[i][1];//tx ,ty 代表下一次想要进入的位置 x y代表的是原来.的位置
if (tx >= 3 || ty >= 3 || tx < 0 || ty < 0 ) {
continue;
}
String num [][] =new String[3][3];
int t =0;
for (int j = 0; j < temporacy.state.length(); j++) {
num[t/3][t%3] = temporacy.state.substring(j,j+1);
t++;
}
String lk = num[tx][ty];
num[tx][ty] = ".";
num[temporacy.x][temporacy.y] = lk;//用于交换位置
String res = "";
for (int j = 0; j < num.length; j++) {
for (int k = 0; k < num.length; k++) {
res +=num[j][k];
}
}
//System.out.println(res);
if (res.equals(endString)) {
System.out.println(temporacy.count+1);
return;
}else {
if (!arrayList.contains(res)) {
arrayList.add(res);
list.addLast(new picture(tx, ty,temporacy.count+1, res));
}
}
}
}
}
}
class picture{//参数:包括当前的的状态,哪些变量一直在变需要记录,记录最后需要的答案
int x;//表示当前的位置
int y;
int count;//表示当前已经走了几步
String state;//表示当前的状态
public picture(int x,int y,int count,String state) {
super();
this.x = x;
this.y=y;
this.count = count;
this.state = state;
}
}