题目:
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
分析:此题用到了bfs和面向对象的思想。用数组,集合等来模拟查找过程。
代码:
package Test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
public class test {
public static String start,end;
public static int x1,y1; // 空白格子的初始坐标
public static int[][] move = {{-1,0},{1,0},{0,-1},{0,1}}; //模拟空白格上下左右移动是坐标的变化
public static HashSet<String> set = new HashSet<String>();//储存每一步的整体状态,用于判断该状态是否出现过。
static class Move{ //面向对象思想,将整个状态封装成一个类。
public int x; //当前状态空白格的横坐标
public int y; //当前状态空白格的纵坐标
public int step; //从初始态到当前这个状态所经过的总步数
public String temp; //当前状态
public Move(int x,int y,int step,String temp){
this.x = x;
this.y = y;
this.step = step;
this.temp = temp;
}
}
public void bfs(){
for (int i = 0; i < start.length(); i++) { //找到初始状态的空白格坐标
if(start.charAt(i)=='.'){
x1 = i/3;
y1 = i%3;
}
}
ArrayList<Move> list = new ArrayList<Move>(); //bfs模拟队列
list.add(new Move(x1,y1,0,start));
set.add(start);
while(!list.isEmpty()){
Move now = list.get(0);
list.remove(0);
if(now.temp.equals(end)){
System.out.println(now.step);
return;
}
for (int i = 0; i < 4; i++) { //模拟上下左右移动的情况
int x = now.x+move[i][0];
int y = now.y+move[i][1];
if(x<0 || x>2 || y<0 || y>2) //判断是否越界 越界则舍去这一步继续
continue;
int step = now.step+1;
char n = now.temp.charAt(x*3+y);
String temp0 = now.temp;
temp0 = temp0.replace(n, '-');
temp0 = temp0.replace('.', n);
temp0 = temp0.replace('-', '.');
if(!set.contains(temp0)){ //判断该步是否出现过,出现过则直接舍去,因为这个必定不是最优,之前已经有步骤到达过。
set.add(temp0);
list.add(new Move(x,y,step,temp0));
}
}
}
System.out.println("-1");
return;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
start = in.next();
end = in.next();
test t = new test();
t.bfs();
}
}