• 骑士游历问题


    由于最近在学习回溯法,所以跟回溯法相关的问题尽量都看下吧。
    骑士游历问题的完整描述见:http://blog.csdn.net/sb___itfk/article/details/50905275

    我的思路

    我的实现如下,还是最简单最粗暴的解法:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * Created by clearbug on 2018/2/26.
     */
    public class Solution {
    
        public static void main(String[] args) {
            Solution s = new Solution();
            long startTime = System.currentTimeMillis();
            List<List<String>> res = s.traverse(5, 0, 0);
            int i = 1;
            for (List<String> item : res) {
                System.out.println("第 " + i + " 种走法:");
                for (String line : item) {
                    System.out.println(line);
                }
                i++;
            }
            long endTime = System.currentTimeMillis();
            System.out.println("运行耗时:" + (endTime - startTime) + " ms");
        }
    
        public List<List<String>> traverse(int N, int sr, int sc) {
            int[][] board = new int[N][N];
            board[sr][sc] = 1;
    
            List<List<String>> res = new ArrayList<>();
            dfs(board, sr, sc, res);
            return res;
        }
    
        private void dfs(int[][] board, int sr, int sc, List<List<String>> res) {
            if (check(board)) {
                List<String> lines = new ArrayList<>();
                for (int i = 0; i < board.length; i++) {
                    lines.add(Arrays.toString(board[i]));
                }
                res.add(lines);
            }
    
            int[] dr = {2, 2, -2, -2, 1, 1, -1, -1};
            int[] dc = {1, -1, 1, -1, 2, -2, 2, -2};
    
            for (int i = 0; i < 8; i++) {
                int[][] newBoard = deepthCopy(board);
                int cr = sr + dr[i];
                int cc = sc + dc[i];
                if (cr >= 0 && cr < board.length && cc >= 0 && cc < board.length && board[cr][cc] == 0) {
                    newBoard[cr][cc] = newBoard[sr][sc] + 1;
                    dfs(newBoard, cr, cc, res);
                }
            }
    
        }
    
        private int[][] deepthCopy(int[][] board) {
            int[][] res = new int[board.length][board.length];
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board.length; j++) {
                    res[i][j] = board[i][j];
                }
            }
            return res;
        }
        
        private boolean check(int[][] board) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board.length; j++) {
                    if (board[i][j] == 0) {
                        return false;
                    }
                }
            }
            return true;
        }
    
    }
    

    运行结果如下:

    第 301 种走法:
    [1, 16, 21, 6, 3]
    [10, 5, 2, 15, 20]
    [17, 22, 11, 4, 7]
    [12, 9, 24, 19, 14]
    [23, 18, 13, 8, 25]
    第 302 种走法:
    [1, 16, 11, 6, 3]
    [10, 5, 2, 21, 12]
    [15, 22, 17, 4, 7]
    [18, 9, 24, 13, 20]
    [23, 14, 19, 8, 25]
    第 303 种走法:
    [1, 16, 11, 6, 3]
    [10, 5, 2, 17, 12]
    [15, 22, 19, 4, 7]
    [20, 9, 24, 13, 18]
    [23, 14, 21, 8, 25]
    第 304 种走法:
    [1, 18, 11, 6, 3]
    [10, 5, 2, 17, 12]
    [19, 22, 13, 4, 7]
    [14, 9, 24, 21, 16]
    [23, 20, 15, 8, 25]
    运行耗时:4073 ms
    

    当 n = 5 时,运行时间已经上 4 秒了。。。可以虽然可以正确运行,但是效率并不 ok
    那么,还是去看看 sb___itfk 这位老铁的解法吧:http://blog.csdn.net/sb___itfk/article/details/50905275

    sb___itfk 解法

    sb___itfk 老铁所描述的算法思路就是:预算下一步的下一步有几种走法,然后走走法最小的那一步。话说起来有点绕,还是看代码,然后我把我的代码和他的代码都写了进来,并运行后比较运行时间:

    import java.util.*;
    
    /**
     * Created by clearbug on 2018/2/26.
     */
    public class Solution {
    
        class TwoIntMap {
            private int next;
            private int nextAvailable;
    
            public TwoIntMap(int next, int nextAvailable) {
                this.next = next;
                this.nextAvailable = nextAvailable;
            }
    
            public int getNext() {
                return next;
            }
    
            public void setNext(int next) {
                this.next = next;
            }
    
            public int getNextAvailable() {
                return nextAvailable;
            }
    
            public void setNextAvailable(int nextAvailable) {
                this.nextAvailable = nextAvailable;
            }
        }
    
        public static void main(String[] args) {
            Solution s = new Solution();
    
            for (int i = 5; i < 9; i++) {
                System.out.println(i + "================================================================================");
                long startTime = System.currentTimeMillis();
                List<String> res = s.traverse(i, 0, 0);
                for (String line : res) {
                    System.out.println(line);
                }
                long endTime = System.currentTimeMillis();
                System.out.println("traverse 运行耗时:" + (endTime - startTime) + " ms");
    
                long startTime2 = System.currentTimeMillis();
                List<String> res2 = s.traverse2(i, 0, 0);
                for (String line : res2) {
                    System.out.println(line);
                }
                long endTime2 = System.currentTimeMillis();
                System.out.println("traverse2 运行耗时:" + (endTime2 - startTime2) + " ms");
            }
        }
    
        public List<String> traverse(int N, int sr, int sc) {
            int[][] board = new int[N][N];
            board[sr][sc] = 1;
    
            List<String> res = new ArrayList<>();
            dfs(board, sr, sc, res);
            return res;
        }
    
        public List<String> traverse2(int N, int sr, int sc) {
            int[][] board = new int[N][N];
            board[sr][sc] = 1;
    
            List<String> res = new ArrayList<>();
            dfs2(board, sr, sc, res);
            return res;
        }
    
        private boolean dfs(int[][] board, int sr, int sc, List<String> res) {
            if (check(board)) {
                for (int i = 0; i < board.length; i++) {
                    res.add(Arrays.toString(board[i]));
                }
                return true;
            }
    
            int[] dr = {2, 2, -2, -2, 1, 1, -1, -1};
            int[] dc = {1, -1, 1, -1, 2, -2, 2, -2};
    
            for (int i = 0; i < 8; i++) {
                int[][] newBoard = deepthCopy(board);
                int cr = sr + dr[i];
                int cc = sc + dc[i];
                if (cr >= 0 && cr < board.length && cc >= 0 && cc < board.length && board[cr][cc] == 0) {
                    newBoard[cr][cc] = newBoard[sr][sc] + 1;
                    if (dfs(newBoard, cr, cc, res)) {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        private boolean dfs2(int[][] board, int sr, int sc, List<String> res) {
            if (check(board)) {
                for (int i = 0; i < board.length; i++) {
                    res.add(Arrays.toString(board[i]));
                }
                return true;
            }
    
            int[] dr = {2, 2, -2, -2, 1, 1, -1, -1};
            int[] dc = {1, -1, 1, -1, 2, -2, 2, -2};
    
            List<TwoIntMap> twoIntMaps = new ArrayList<>();
    
            for (int i = 0; i < 8; i++) {
                int[][] newBoard = deepthCopy(board);
                int cr = sr + dr[i];
                int cc = sc + dc[i];
                if (cr >= 0 && cr < board.length && cc >= 0 && cc < board.length && board[cr][cc] == 0) {
                    newBoard[cr][cc] = newBoard[sr][sc] + 1;
                    twoIntMaps.add(new TwoIntMap(i, nextStepAvailableDirection(newBoard, cr, cc)));
                }
            }
    
            twoIntMaps.sort(Comparator.comparingInt(TwoIntMap::getNextAvailable));
            for (TwoIntMap twoIntMap : twoIntMaps) {
                int[][] newBoard = deepthCopy(board);
                int cr = sr + dr[twoIntMap.getNext()];
                int cc = sc + dc[twoIntMap.getNext()];
                newBoard[cr][cc] = newBoard[sr][sc] + 1;
                if (dfs2(newBoard, cr, cc, res)) {
                    return true;
                }
    
            }
    
            return false;
        }
    
        private int[][] deepthCopy(int[][] board) {
            int[][] res = new int[board.length][board.length];
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board.length; j++) {
                    res[i][j] = board[i][j];
                }
            }
            return res;
        }
    
        private boolean check(int[][] board) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board.length; j++) {
                    if (board[i][j] == 0) {
                        return false;
                    }
                }
            }
            return true;
        }
    
        private int nextStepAvailableDirection(int[][] board, int sr, int sc) {
            int res = 0;
    
            int[] dr = {2, 2, -2, -2, 1, 1, -1, -1};
            int[] dc = {1, -1, 1, -1, 2, -2, 2, -2};
    
            for (int i = 0; i < 8; i++) {
                int cr = sr + dr[i];
                int cc = sc + dc[i];
                if (cr >= 0 && cr < board.length && cc >= 0 && cc < board.length && board[cr][cc] == 0) {
                    res++;
                }
            }
    
            return res;
        }
    
    }
    

    运行结果:

    5================================================================================
    [1, 6, 15, 10, 21]
    [14, 9, 20, 5, 16]
    [19, 2, 7, 22, 11]
    [8, 13, 24, 17, 4]
    [25, 18, 3, 12, 23]
    traverse 运行耗时:216 ms
    [1, 22, 11, 16, 7]
    [12, 17, 8, 21, 10]
    [25, 2, 23, 6, 15]
    [18, 13, 4, 9, 20]
    [3, 24, 19, 14, 5]
    traverse2 运行耗时:54 ms
    6================================================================================
    [1, 12, 21, 28, 7, 10]
    [22, 29, 8, 11, 20, 27]
    [13, 2, 23, 4, 9, 6]
    [30, 35, 32, 17, 26, 19]
    [33, 14, 3, 24, 5, 16]
    [36, 31, 34, 15, 18, 25]
    traverse 运行耗时:6646 ms
    [1, 10, 31, 20, 7, 12]
    [32, 19, 8, 11, 30, 21]
    [9, 2, 25, 36, 13, 6]
    [18, 33, 16, 27, 22, 29]
    [3, 26, 35, 24, 5, 14]
    [34, 17, 4, 15, 28, 23]
    traverse2 运行耗时:1 ms
    7================================================================================
    [1, 28, 37, 40, 25, 30, 9]
    [38, 41, 26, 29, 10, 35, 24]
    [27, 2, 39, 36, 23, 8, 31]
    [42, 19, 44, 17, 32, 11, 34]
    [45, 48, 3, 22, 5, 14, 7]
    [20, 43, 18, 47, 16, 33, 12]
    [49, 46, 21, 4, 13, 6, 15]
    traverse 运行耗时:474 ms
    [1, 30, 11, 46, 27, 32, 9]
    [12, 45, 28, 31, 10, 37, 26]
    [29, 2, 49, 38, 47, 8, 33]
    [42, 13, 44, 19, 34, 25, 36]
    [3, 16, 41, 48, 39, 22, 7]
    [14, 43, 18, 5, 20, 35, 24]
    [17, 4, 15, 40, 23, 6, 21]
    traverse2 运行耗时:1 ms
    8================================================================================
    

    从 i = 5,6,7 的运行情况,使用预测算法的确节省了很多时间,效率提高了几十到上百倍。然而,i = 8 的运行结果迟迟不出来,我都运行了半个小时了还没运算出来。。。等运算完毕了再回来更新吧!

    参考

    http://blog.csdn.net/sb___itfk/article/details/50905275

  • 相关阅读:
    Redis
    Log4Net
    EF脚手架生成数据库上下文(scaffold-dbcontext)
    quartz.net
    基于LNMP的小米电子商务网站平台
    LVS的DR模式负载均衡
    华为交换机SSH配置
    VMware ESXi 6.5安装
    VLAN划分
    华为路由设备SSH配置
  • 原文地址:https://www.cnblogs.com/optor/p/8529026.html
Copyright © 2020-2023  润新知