美文网首页
BFS——练习题——密码锁

BFS——练习题——密码锁

作者: markeNick | 来源:发表于2020-02-09 00:55 被阅读0次

    基本模型

    void bfs() {    // 传入起始点
        // 1.将起始点放入队列中
        
        // 2.标记起点访问
        
        while() {   // 如果队列不为空
            // 3.访问队列中队首元素x
            
            // 4.删除队首元素
            
            for(){  // 遍历x所有相邻点
                if() {  // 如果该点未被访问过且合法   
                    // 5.将该点加入队列末尾
                }
            }
        }
    }
    

    练习题

    1.密码锁

    现在一个紧急的任务是打开一个密码锁。 密码由四位数字组成,每个数字从1到9进行编码。每次可以对任何一位数字加1或减1。当将9加1时,数字将变为1,当将1减1时,数字将变为9.你也可以交换相邻数字,每一个行动记作异步。现在你的任务是使用最小的步骤来打开锁。注意:最左边的数字不与最右边的数字相邻。

    输入格式:
    第一行输入四位数字,表示密码锁的初始状态。
    第二行输入四位数字,表示开锁的密码。

    输出格式:
    输出一个整数,表示最小步骤。

    输入样例:
    1234
    2144

    输出样例:
    2

    思路:

    首先处理输入和初始化队列,以Node类模拟一个四位数数字,分别列出三种情况(加1、减1、交换相邻两个数),然后循环取出队列首元素判断是否满足退出条件,不满足则进行三种情况的操作。
    第一种情况是:将取出来的队首元素的每个数字进行加1,然后逐个放入到队列中去,注意第一个for循环下来,共有四个Node被放到队列中去,且每个Node的step都是一样的(都为1)
    比如:1234,取出1234这个Node,克隆一份,加1就是2234(step=1)放入队列中,接着再克隆一份1234这个Node,再加1就是1334,以此类推。(每次都在1234的基础上加1,只不过加的位数不同),所以对1234进行加1的操作产生的队列是就2234 1334 1244 1235(step都为1)。
    其他情况类似。

    注意:如果Node next = now;则next保存的是now的引用,修改next同时也修改了now,因此需要使用java的深克隆(Node类中的含有数组)

    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    
    /**
     * 计蒜客——密码锁
     * @author 无处安身
     *
     */
    public class Main {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            
            Scanner sc = new Scanner(System.in);
            
            char[] arr1 = sc.nextLine().toCharArray();
            char[] arr2 = sc.nextLine().toCharArray();
            
            
            Node first = new Node();    // 密码锁初始状态
            Node last = new Node();     // 开锁的密码
            
            for(int i = 0; i < 4; i++) {
                first.num[i] = arr1[i] - '0';
                last.num[i] = arr2[i] - '0';
            }
            
            int[][][][] vis = new int[11][11][11][11];
            Queue<Node> queue = new LinkedList<Node>();
            
            queue.add(first);
            vis[first.num[0]][first.num[1]][first.num[2]][first.num[3]] = 1;
            
            while(!queue.isEmpty()) {
                Node now = queue.poll();
                
                // 如果找到了开锁的密码就退出
                if(isKey(now, last)) {
                    System.out.println(now.step);
                    return;
                }
    
                // 加1的情况
                for (int i = 0; i < 4; i++) {               
                    Node next = (Node) now.clone();
                    next.num[i]++;
                    if(next.num[i] == 9) 
                        next.num[i] = 1;
                    
                    if(check(next, vis)) {
                        vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                        next.step++;
                        queue.add((Node) next.clone());
                    }
                }
                
                // 减1的情况
                for (int i = 0; i < 4; i++) {
                    Node next = (Node) now.clone();
                    next.num[i]++;
                    if(next.num[i] == 1) 
                        next.num[i] = 9;
                    
                    if(check(next, vis)) {
                        vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                        next.step++;
                        queue.add((Node) next.clone());
                    }
                }
                
                // 交换2个数的情况
                for(int i = 0; i < 3; i++) {
                    Node next = (Node) now.clone();
                    int temp=next.num[i+1];
                    next.num[i+1]=next.num[i];
                    next.num[i]=temp;
                    
                    if(check(next, vis)) {
                        vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                        next.step++;
                        queue.add((Node) next.clone());
                    }
                }
            }       
        }
    
        
        // 检查这个四位数是否访问过
        public static boolean check(Node next, int[][][][] vis) {
            
            return vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] == 0;
        }
        
    
        // 检查是不是开锁的密码
        public static boolean isKey(Node now, Node last) {
            
            return now.num[0] == last.num[0] && now.num[1] == last.num[1] && 
                    now.num[2] == last.num[2] && now.num[3] == last.num[3];
        }
        
        static class Node implements Cloneable {
            int[] num = new int[4];
            int step = 0;
            
            Node() {
                
            }
            
            Node(int a,int b,int c,int d,int step){
                this.num[0]=a;
                this.num[1]=b;
                this.num[2]=c;
                this.num[3]=d;
                this.step=step;
            }
            
            @Override
            protected Object clone() throws CloneNotSupportedException {
                Node node = (Node) super.clone();
                node.num = new int[4];
                System.arraycopy(this.num, 0, node.num, 0, 4);
                
                return node;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:BFS——练习题——密码锁

          本文链接:https://www.haomeiwen.com/subject/imawxhtx.html