历届试题 九宫重排
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
解题思路:
比较经典的搜索题,可以直接搜索或者使用双向搜索优化。
AC代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
public class Main {
static Map<String,Integer> hm1 = new HashMap<String,Integer>();
static Map<String,Integer> hm2 = new HashMap<String,Integer>();
static int[] dx = {-1,0,1,0},dy = {0,-1,0,1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String start = br.readLine();
String end = br.readLine();
char[][] a = new char[3][3];
char[][] b = new char[3][3];
int pos = 0,x1 = 0,y1 = 0,x2 = 0,y2 = 0;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
a[i][j] = start.charAt(pos);
b[i][j] = end.charAt(pos);
pos++;
if(a[i][j] == '.'){
x1 = i;
y1 = j;
}
if(b[i][j] == '.'){
x2 = i;
y2 = j;
}
}
}
Node node1 = new Node(0,x1,y1,a);
Node node2 = new Node(0,x2,y2,b);
Queue<Node> qnode1 = new LinkedList<Node>();
Queue<Node> qnode2 = new LinkedList<Node>();
qnode1.add(node1);
qnode2.add(node2);
hm1.put(node1.getMap(), 0);
hm2.put(node2.getMap(), 0);
System.out.println(bfs(qnode1,qnode2));
}
private static int bfs(Queue<Node> q1, Queue<Node> q2) {
while(!q1.isEmpty() || !q2.isEmpty()){
if(!q1.isEmpty()){
Node node = q1.poll();
int x = node.getX();
int y = node.getY();
if(hm2.containsKey(node.getMap())){
return node.getSum() + hm2.get(node.getMap());
}
for(int i = 0; i < 4; i++){
int xx = x+dx[i],yy = y+dy[i];
if(xx < 0 || xx >= 3 || yy < 0 || yy >= 3)
continue;
char[][] a = node.getCopy();
a[x][y] = a[xx][yy];
a[xx][yy] = '.';
Node node2 = new Node(node.sum+1,xx,yy,a);
String s = node2.getMap();
if(hm2.containsKey(s)){
return node2.getSum()+hm2.get(s);
}
if(!hm1.containsKey(s)){
hm1.put(s, node2.getSum());
q1.add(node2);
}
}
}
if(!q2.isEmpty()){
Node node = q2.poll();
int x = node.getX();
int y = node.getY();
if(hm1.containsKey(node.getMap())){
return node.getSum() + hm1.get(node.getMap());
}
for(int i = 0; i < 4; i++){
int xx = x+dx[i],yy = y+dy[i];
if(xx < 0 || xx >= 3 || yy < 0 || yy >= 3)
continue;
char[][] a = node.getCopy();
a[x][y] = a[xx][yy];
a[xx][yy] = '.';
Node node2 = new Node(node.sum+1,xx,yy,a);
String s = node2.getMap();
if(hm1.containsKey(s)){
return node2.getSum()+hm1.get(s);
}
if(!hm2.containsKey(s)){
hm2.put(s, node2.getSum());
q2.add(node2);
}
}
}
}
return -1;
}
}
class Node{
int sum,x,y;
char[][] a = null;
public char[][] getCopy(){
char[][] copy = new char[3][3];
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
copy[i][j] = a[i][j];
}
}
return copy;
}
public String getMap(){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
sb.append(a[i][j]);
}
}
return sb.toString();
}
public Node(int sum, int x, int y, char[][] a) {
super();
this.sum = sum;
this.x = x;
this.y = y;
this.a = a;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
测试数据:
Input:
12345678.
152743.86
12345678.
12356.784
2315.6784
8235164.7
12345678.
87654321.
.87654321
12345678.
Output:
6
13
17
30
28