zoukankan      html  css  js  c++  java
  • 2013年第四届蓝桥杯国赛 九宫重排(HashMap+双BFS优化)

    九宫重排  
     
    时间限制:1.0s   内存限制:256.0MB

    问题描述
      如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

      我们把第一个图的局面记为:12345678.
      把第二个图的局面记为:123.46758
      显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
      本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
     
    输入格式
      输入第一行包含九宫的初态,第二行包含九宫的终态。
    输出格式
      输出最少的步数,如果不存在方案,则输出-1。
     
    样例输入
    12345678.
    123.46758
     
    样例输出
    3
     
    样例输入
    13524678.
    46758123.
     
    样例输出
    22
     
     
    BFS。将字符串视作状态,将“.”视作位移点,每次向四个方向移动的同时交换字符。
     
    很明显需要用到HashMap来记录状态,开始时图方便我把字符串转换成二维数组作为HashMap的键值,然后就遇到各种问题。。
    首先二维数组作为键值记录的是地址而并非数组元素,所以即使是两个相同的数组代表的也是不同的键值。
    其次用二维数组来进行操作效率极低。。
    最终还是回到了字符串处理上,用一维来表示二维状态,仔细推敲后其实并不麻烦(详见代码)。
    注意字符交换时replace用到的小技巧。
     
    然后就是算法方面了,这道题用bfs显然是可做的:
    import java.util.ArrayDeque;
    import java.util.HashMap;
    import java.util.Scanner;
    
    public class Main {
    
        static Scanner sc = new Scanner(System.in);
        static String beg,end;
        static int[][] t = {{1,0},{0,1},{-1,0},{0,-1}};
        static HashMap<String,Integer> b = new HashMap<String,Integer>();
        static class Node{
            String a;
            int x,s;
            public Node(String a,int x,int s) {
                this.a=a;
                this.x=x;
                this.s=s;
            }
        }
        static ArrayDeque<Node> q = new ArrayDeque<Node>();
        
        static int bfs(int bx,int ex) {
            
            b.put(end, -1);
            if(b.get(beg)!=null) return 0;
            b.put(beg, 0);
            q.offerLast(new Node(beg,bx,0));
            while(q.size()>0) {
                String a=q.peekFirst().a;
                int x=q.peekFirst().x/3;
                int y=q.peekFirst().x%3;
                int s=q.peekFirst().s;
                q.pollFirst();
                for(int i=0;i<4;i++) {
                    int tx=x+t[i][0];
                    int ty=y+t[i][1];
                    if(tx<0||ty<0||tx>=3||ty>=3) continue;
                    char tt=a.charAt(tx*3+ty);
                    String ta=a;
                    ta=ta.replace(tt, '!');
                    ta=ta.replace('.', tt);
                    ta=ta.replace('!', '.');
                    if(b.get(ta)!=null){
                        if(b.get(ta)==-1) return s+1;
                        continue;
                    }
                    b.put(ta, s+1);
                    q.offerLast(new Node(ta,tx*3+ty,s+1));
                }
            }
            return -1;
        }
        
        public static void main(String[] args) {
            
            beg = sc.next();
            end = sc.next();
            int bx=0,ex=0;
            for(int i=0;i<9;i++) {
                if(beg.charAt(i)=='.'){
                    bx=i;
                    break;
                }
            }
            for(int i=0;i<9;i++) {
                if(end.charAt(i)=='.'){
                    ex=i;
                    break;
                }
            }
            System.out.println(bfs(bx,ex));
        }
    
    }
    优化前
    但官网提交显示只过了80%数据
     
    因此需要想到使用双起点bfs优化,起点终点一起搜,大大减少了分支情况。
    碰头时两边步数+当前1即为最终解。
    import java.util.ArrayDeque;
    import java.util.HashMap;
    import java.util.Scanner;
    
    public class Main {
    
        static Scanner sc = new Scanner(System.in);
        static String beg,end;
        static int[][] t = {{1,0},{0,1},{-1,0},{0,-1}};
        static HashMap<String,Integer> bb = new HashMap<String,Integer>();
        static HashMap<String,Integer> be = new HashMap<String,Integer>();
        static class Node{
            String a;
            int x,s,m;
            public Node(String a,int x,int s,int m) {
                this.a=a;
                this.x=x;
                this.s=s;
                this.m=m;
            }
        }
        static ArrayDeque<Node> q = new ArrayDeque<Node>();
        
        static int bfs(int bx,int ex) {
            
            if(beg.equals(end)) return 0;
            bb.put(beg, 0);be.put(end, 0);
            q.offerLast(new Node(beg,bx,0,1));
            q.offerLast(new Node(end,ex,0,2));
            while(q.size()>0) {
                String a=q.peekFirst().a;
                int x=q.peekFirst().x/3;
                int y=q.peekFirst().x%3;
                int s=q.peekFirst().s;
                int m=q.peekFirst().m;
                q.pollFirst();
                for(int i=0;i<4;i++) {
                    int tx=x+t[i][0];
                    int ty=y+t[i][1];
                    if(tx<0||ty<0||tx>=3||ty>=3) continue;
                    char tt=a.charAt(tx*3+ty);
                    String ta=a;
                    ta=ta.replace(tt, '!');
                    ta=ta.replace('.', tt);
                    ta=ta.replace('!', '.');
                    if(m==1){
                        if(bb.get(ta)!=null) continue;
                        if(be.get(ta)!=null) return be.get(ta)+s+1;
                        bb.put(ta, s+1);
                    }
                    else{
                        if(be.get(ta)!=null) continue;
                        if(bb.get(ta)!=null) return bb.get(ta)+s+1;
                        be.put(ta, s+1);
                    }
                    q.offerLast(new Node(ta,tx*3+ty,s+1,m));
                }
            }
            return -1;
        }
        
        public static void main(String[] args) {
            
            beg = sc.next();
            end = sc.next();
            int bx=0,ex=0;
            for(int i=0;i<9;i++) {
                if(beg.charAt(i)=='.'){
                    bx=i;
                    break;
                }
            }
            for(int i=0;i<9;i++) {
                if(end.charAt(i)=='.'){
                    ex=i;
                    break;
                }
            }
            System.out.println(bfs(bx,ex));
        }
    
    }
    优化后
  • 相关阅读:
    Log4j详细介绍(五)----输出地Appender
    Java抽象类与接口的区别
    深入理解Java的接口和抽象类
    小程序
    小程序
    小程序
    CMS
    CMS
    微信小程序
    微信小程序
  • 原文地址:https://www.cnblogs.com/yzm10/p/10657630.html
Copyright © 2011-2022 走看看