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

    双向广搜


  • 相关阅读:
    结构体初体验
    hdu 2068 RPG的错排
    hdu 2160 母猪的故事
    python爬虫从入门到放弃(一)——试用bs4, request爬百度股票
    python web开发c6——阿里云上ubuntu+flask+gunicorn+nginx服务器部署(一)简单测试
    python web开发——c5 图片上传 flask-uploads 云储存sdk
    python web开发——c3 数据库交互和flask-SQLALchemy
    python web开发——c2 flask框架和flask_script
    javar入门——基本数据类型
    java入门——面向对象
  • 原文地址:https://www.cnblogs.com/james1207/p/3260447.html
Copyright © 2020-2023  润新知