您的位置:首页 > 其它

蓝桥杯 历届试题 九宫重排(双向搜索优化)

2016-03-09 15:00 525 查看

  历届试题 九宫重排  

问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。





  我们把第一个图的局面记为:12345678.

  把第二个图的局面记为:123.46758

  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。

  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.

123.46758

样例输出

3

样例输入

13524678.

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  双向搜索