Eleven puzzle

Time Limit: 20000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 463    Accepted Submission(s): 111

Problem Description
Partychen invents a new game named “Eleven Puzzle” .Just like the classic game “Eight Puzzle”,but there some difference between them:The shape of the board is different and there are two empty tiles.
Eleven puzzle_hdu_3095(双向广搜).java_数据

The tile in black means it’s empty 

Each step you can move only one tile.
Here comes the problem.How many steps at least it required to done the game.
 

 

Input
The first line of input contains one integer specifying the number of test cases to follow.
Every case contains five lines to describe the initial status of the board. 0 means empty.

It’s confirmed that the board is legal.
 

 

Output
Output one line for each testcase.Contain an integer denotes the minimum step(s) it need to complete the game.Or “No solution!” if it’s impossible to complete the game within 20 steps.
 

 

Sample Input
3 2 1 0 3 4 5 6 7 8 9 0 11 10 0 1 2 3 4 5 6 7 8 9 10 11 0 0 11 10 9 8 7 6 5 4 3 2 1 0
 

 

Sample Output
2 0 No solution!
 
//8953704	2013-08-15 15:45:09	Accepted	3095	2562MS	27052K	6524 B	Java	zhangyi
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;

public class Hdu3095 {
	private static Map<String,Integer> smap = new HashMap<String,Integer>();   //存储从初始状态搜索所到达的状态
	private static Map<String, Integer> emap = new HashMap<String, Integer>();//存储从目的状态搜索所到达的状态
	private static Status sStatus = null; //初始状态
	private static Status eStatus = null;//目的状态
	private static int [][] dirs = new int[][]{{1,0},{-1,0},{0,-1},{0,1}}; //方向
	private static Queue<Status> sq = new ArrayDeque<Status>();
	private static Queue<Status> eq = new ArrayDeque<Status>();
	private final static Integer maxLevel = 10;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int cases = in.nextInt();
		while(cases-->0){
			inputData(in);
			if(eStatus.getStatus().equals(sStatus.getStatus())){//如果初始状态等于目的状态,输出0
				System.out.println(0);
			}else{
				emap.put(eStatus.getStatus(), 0);
				smap.put(sStatus.getStatus(), 0);
				int step = doublcBFS(sq,eq);
				if(step == -1 || step > 20){
					System.out.println("No solution!");
				}else{
					System.out.println(step);
				}
			}
		}
	}
	/**
	 * 输入数据
	 * @param in
	 */
	private static void inputData(Scanner in){
		initResourse();
		int value = 0;
		sStatus.map[1][3] = in.nextInt();
		eStatus.map[1][3] = value++;
		for(int i = 2; i <= 4; ++i){
			sStatus.map[2][i] = in.nextInt();
			eStatus.map[2][i] = value++;
		}
		for(int i = 1; i <= 5; ++i){
			sStatus.map[3][i] = in.nextInt();
			eStatus.map[3][i] = value++;
		}
		for(int i = 2; i <= 4; ++i){
			sStatus.map[4][i] = in.nextInt();
			eStatus.map[4][i] = value++;
		}
		sStatus.map[5][3] = in.nextInt();
		eStatus.map[5][3] = 0;
		smap.clear();
		emap.clear();
		sStatus.initPoint();
		eStatus.initPoint();
		sq.clear();
		eq.clear();
		sq.add(sStatus);
		eq.add(eStatus);
	}

	/**
	 * 初始化数据
	 */
	private static void initResourse(){
		sStatus = new Status();
		eStatus = new Status();
		for(int i = 0;i < sStatus.map.length; ++i){
			Arrays.fill(sStatus.map[i], -1);
			Arrays.fill(eStatus.map[i], -1);
		}
	}

	/**
	 * 双向搜索函数
	 * @param sq 初始状态搜索所需要的队列
	 * @param eq 目的状态搜索所需要的队列
	 * @return 初始状态到达目的状态所需要的最小步数,如果在maxLevel数值之内没有结果,则返回-1
	 */
	private static int doublcBFS(Queue<Status> sq, Queue<Status> eq){
		int x, y;
		while(!sq.isEmpty()||!eq.isEmpty()){
			if(!sq.isEmpty()){ //初始状态搜索
				Status s = sq.poll();
				for(int i = 0; i < s.points.size(); ++i ){
					Point p = s.points.get(i);
					for(int j = 0; j < dirs.length; ++j){
						x = p.x + dirs[j][0];
						y = p.y + dirs[j][1];
						if(s.map[x][y] == -1 || s.map[x][y] == 0){
							continue;
						}
						int [][] ms = copyArray(s.map);

						ms[p.x][p.y] = ms[x][y];
						ms[x][y] = 0;

						Status status = new Status();
						status.map = ms;
						status.points.add(new Point(x,y));
						status.points.add(s.points.get((i+1)%2).copyPoint());
						status.level = s.level + 1;
						String ss = status.getStatus();
						if(emap.containsKey(ss)){   //如果与目的状态搜索到的状态相遇,刚返回步数
							return emap.get(ss) + status.level;
						}
						if(!smap.containsKey(ss) && s.level <= maxLevel){
							smap.put(ss, status.level);
							sq.add(status);
						}
					}
				}
			}
			if(!eq.isEmpty()){ //目的状态搜索
				Status s = eq.poll();
				for(int i = 0; i < s.points.size(); ++i ){
					Point p = s.points.get(i);
					for(int j = 0; j < dirs.length; ++j){
						x = p.x + dirs[j][0];
						y = p.y + dirs[j][1];
						if(s.map[x][y] == -1 || s.map[x][y] == 0){
							continue;
						}
						int [][] ms = copyArray(s.map);
						ms[p.x][p.y] = ms[x][y];
						ms[x][y] = 0;

						Status status = new Status();
						status.map = ms;
						status.points.add(new Point(x,y));
						status.points.add(s.points.get((i+1)%2).copyPoint());
						status.level = s.level + 1;
						String ss = status.getStatus();
						if(smap.containsKey(ss)){//如果与初始状态搜索到的状态相遇,刚返回步数
							return smap.get(ss) + status.level;
						}
						if(!emap.containsKey(ss) && s.level <= maxLevel){
							emap.put(ss, status.level);
							eq.add(status);
						}
					}
				}
			}
		}
		return -1;
	}


	/**
	 * 打印一个二维数组
	 * @param map
	 */
	private static void show(int [][] map){
		StringBuilder sb = new StringBuilder();
		for(int i = 1; i < map.length - 1; ++i){
			for(int j = 1; j < map[i].length - 1; ++j){
				if(map[i][j] == -1){
					sb.append(' ');
				}else{
					sb.append(map[i][j]);
				}
			}
			sb.append('\n');
		}
		System.out.println(sb.toString());
	}

	/**
	 * 拷贝一个二维数组
	 * @param map
	 * @return
	 */
	private static int[][] copyArray(int [][] map){
		int [][] m = new int[map.length][map[0].length];
		for(int i = 0; i < map.length; ++i){
			System.arraycopy(map[i],0,m[i],0,map[i].length);
		}
		return m;
	}
}

/**
 * 存储状态
 * @author Administrator
 *
 */
class Status{
	final static int N = 7;
	int [][] map; //当前地图
	List<Point> points; //当前0点坐标
	int level = 0; //到达当前状态所需步数
	public Status(){
		map = new int[N][N];
		points = new ArrayList<Point>();
		level = 0;
	}
	public Status(int [][] map, List<Point> points, int level){
		this.map = map;
		this.points = points;
		this.level = level;
	}
	public void initPoint(){
		for(int i = 1; i < map.length -1; ++i){
			for(int j = 1; j < map[i].length - 1; ++j){
				if(map[i][j] == 0){
					points.add(new Point(i,j));
				}
			}
		}
	}

	/**
	 * 返回一个可唯一标识当前状态的字符串
	 * @return
	 */
	public  String getStatus(){
		StringBuilder sb = new StringBuilder();
		for(int i = 1; i < map.length -1; ++i){
			for(int j = 1; j < map[i].length -1; ++j){
				if(map[i][j] != -1){
					sb.append(map[i][j]);
					sb.append(',');
				}
			}
		}
		return sb.toString();
	}
}
/**
 * 坐标
 * @author Administrator
 *
 */
class Point{
	int x;
	int y;
	public Point(){

	}
	public Point(int x, int y){
		this.x = x;
		this.y = y;
	}
	/**
	 * 拷贝一个坐标
	 * @return
	 */
	public Point copyPoint(){
		Point p = new Point();
		p.x = x;
		p.y = y;
		return p;
	}
}

双向广搜