zoukankan      html  css  js  c++  java
  • leetcode773

    On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0.
    A move consists of choosing 0 and a 4-directionally adjacent number and swapping it.
    The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]].
    Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1.
    Examples:
    Input: board = [[1,2,3],[4,0,5]]
    Output: 1
    Explanation: Swap the 0 and the 5 in one move.
    Input: board = [[1,2,3],[5,4,0]]
    Output: -1
    Explanation: No number of moves will make the board solved.
    Input: board = [[4,1,2],[5,0,3]]
    Output: 5
    Note:
    * board will be a 2 x 3 array as described above.
    * board[i][j] will be a permutation of [0, 1, 2, 3, 4, 5].

    层级遍历的BFS。
    算法原因:一层层扩展出去的找答案,找到答案的瞬间一定是最近的方法。DFS也有办法搜到答案,但你不能保证你搜到的那个是最短的,你得搜完所有可能的答案并且每次搜到的时候打一次擂台才能保证正确性,时间复杂度会不如BFS。
    算法辅助:需要用一个标识符标识状态,加入set从而避免重复搜索。本题不能直接保存int[][]格式的board,你可以转化为String后放入set。所以要有string和board的来回转换。

    细节:
    1.层级遍历的while循环内最后一行别忘了写step++,一写长就忘,很多次了。
    2.在上下左右去尝试swap的时候,swap完别忘了换回去,这题要回溯,因为你四次尝试swap的对象board是同一个int[][],不像其他题目BFS是比较简单的数据结构。
    3.取出一个crt以后去上下左右尝试动0,swap的时候注意swap对象是crt不是整个函数传入的board。对当前这一步进行修改,而不是算出一个0的位置后拿着这个位置回到最初的棋盘上乱改。

    实现:

    class Solution {
        private class Pair {
            public int x;
            public int y;
            public Pair(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
        public int slidingPuzzle(int[][] board) {
            
            int[] dx = {0, 1, 0, -1};
            int[] dy = {-1, 0, 1, 0};
            Queue<String> q = new LinkedList<>();
            Set<String> set = new HashSet<>();
            
            String s = boardToString(board);
            q.offer(s);
            set.add(s);
            
            int step = 0;
            while (!q.isEmpty()) {
                int size = q.size();
                for (int round = 0; round < size; round++) {
                    s = q.poll();
                    if (isSolved(s)) {
                        return step;
                    }
    
                    int[][] crt = stringToBoard(s);
                    Pair zeroIdx = findZero(crt);
                    int x = zeroIdx.x, y = zeroIdx.y;
                    
                    for (int i = 0; i < 4; i++) {
                        int nx = x + dx[i];
                        int ny = y + dy[i];
                        if (!isValid(crt, nx, ny)) {
                            continue;
                        }
                        // P3: 这里要swap的对象是crt不是board!!!你要对你提取出来的这一步的棋盘做修改啊不是最开始的。
                        swap(crt, x, y, nx, ny);
                        String ns = boardToString(crt);
                        if (!set.contains(ns)) {
                            set.add(ns);
                            q.offer(ns);
                        }
                        // P2: 这里千万记住要回溯回去!!!!因为你一直在用同一个crt不是新建!不回去你下一次循环会错的!
                        swap(crt, x, y, nx, ny);
                    }
                }
                // P1: 别忘了层级遍历的增加层数!!!!!
                step++;
            }
            return -1;
        }
        
        private String boardToString(int[][] board) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 6; i++) {
                sb.append(board[i / 3][i % 3]);
            }
            return sb.toString();
        }
        
        private int[][] stringToBoard(String s) {
            int[][] ans = new int[2][3];
            for (int i = 0; i < 6; i++) {
                ans[i / 3][i % 3] = s.charAt(i) - '0';
            }
            return ans;
        }
        
        private Pair findZero(int[][] board) {
            int x = 0, y = 0;
            for (int i = 0; i < 6; i++) {
                if (board[i / 3][i % 3] == 0) {
                    x = i / 3;
                    y = i % 3;
                }
            }
            return new Pair(x, y);
        }
        
        private boolean isSolved(String s) {
            return "123450".equals(s);
        }
        
        private boolean isValid(int[][] board, int x, int y) {
            return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
        }
        
        private void swap(int[][] board, int x1, int y1, int x2, int y2) {
            int temp = board[x1][y1];
            board[x1][y1] = board[x2][y2];
            board[x2][y2] = temp;
        }
    }
  • 相关阅读:
    【Ruby on Rails 学习五】Ruby语言的方法
    【Ruby on Rails 学习六】Ruby 类 的入门
    【Ruby on Rails 学习三】Ruby 基本数据类型(类、类的实例、对象)
    【深度学习笔记】第 1 课:从机器学习到深度学习
    【Ruby on Rails学习二】在线学习资料的整理
    【Ruby on Rails 学习一】ubuntu14.04配置rvm与ruby
    THREE.JS + Blender(obj、mtl加载代码)
    全站查询和分页显示——在线留言板2
    增加留言版块——在线留言板1
    html加载速度技术点
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9672756.html
Copyright © 2011-2022 走看看