Hdu acm 3095

package cn.edu.hpu.hdu;

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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值