• Eleven puzzle_hdu_3095(双向广搜).java


    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('
    ');
    		}
    		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;
    	}
    }

    双向广搜


  • 相关阅读:
    多组件共享-vuex
    在子组件中触发事件,传值给父组件-vue
    在父组件中,直接获取子组件数据-vue
    非父子组件通过事件传值-vue
    在父组件中,传值给子组件-vue
    MVVM
    Virtual DOM-渲染函数render -vue
    duilib入门简明教程 -- VS环境配置(2) (转)
    duilib入门简明教程 -- 前言(1) (转)
    【CDockablePane】关于CDockablePane
  • 原文地址:https://www.cnblogs.com/james1207/p/3260447.html
Copyright © 2020-2023  润新知