Eleven puzzle_hdu_3095(双向广搜).java

53 篇文章 0 订阅
29 篇文章 0 订阅

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.

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;
	}
}

双向广搜


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值