骑士游历问题

由于最近在学习回溯法,所以跟回溯法相关的问题尽量都看下吧。

骑士游历问题的完整描述见: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 解法

参考

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

原文地址:https://www.cnblogs.com/optor/p/8529026.html

时间: 2024-10-13 09:22:00

骑士游历问题的相关文章

骑士游历

理论: 骑士游历问题是放在8×8的国际象棋棋盘上的一个马,按照马走"日"字的规则是否能够不重复地走遍棋盘的每个格. 解答: 每次选取下一次走法最少的走,但总是游历失败. java实现: package 经典; public class Knight { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int[][] board=new int

骑士游历/knight tour - visual basic 解决

在visual baisc 6 how to program 中文版第七章的练习题上看到了这个问题,骑士游历的问题. 在8x8的国际象棋的棋盘上,骑士(走法:一个方向走两格,另一个方向一格)不重复走完棋盘上所有空格的路径. 思路就是选角落的一格为起点,把所有能走的路全部路径全部试一遍.要试8^63次,计算时间太长了.把棋盘调成5x5的,比较好算.另外书里提示,根据空格的可访问的难易(难易由周围可访问它的空格数来决定),先选择更难访问的空格访问. 下面是完全遍历一遍的方法. Option Expl

POJ 2488 -- A Knight&#39;s Journey(骑士游历)

POJ 2488 -- A Knight's Journey(骑士游历) 题意: 给出一个国际棋盘的大小,判断马能否不重复的走过所有格,并记录下其中按字典序排列的第一种路径. 经典的"骑士游历"问题 输入:第一行,整数n,接下来是n行,每一行为p和q,p为行数,q为列数,p用1...p编号,q用A...Q编号 马的走法:每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走"日"字).可以越子,没有中国象棋中的"蹩马腿&

HihoCoder 1504 : 骑士游历 (矩阵乘法)

描述 在8x8的国际象棋棋盘上给定一只骑士(俗称“马”)棋子的位置(R, C),小Hi想知道从(R, C)开始移动N步一共有多少种不同的走法. 输入 第一行包含三个整数,N,R和C. 对于40%的数据, 1 <= N <= 1000000 对于100%的数据, 1 <= N <= 1000000000 1 <= R, C <= 8 输出 从(R, C)开始走N步有多少种不同的走法.由于答案可能非常大,你只需要输出答案模1000000007的余数. 样例输入 2 1 1

codevs——T1219 骑士游历

 http://codevs.cn/problem/1219/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个

codevs 1219 骑士游历 1997年

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个整数x1,y1,x2,y2 输出描述 Output Description 输出方案

hihocoder offer收割编程练习赛13 D 骑士游历

思路: 矩阵快速幂. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 using namespace std; 5 6 typedef long long ll; 7 typedef vector<ll> vec; 8 typedef vector<vec> mat; 9 10 const ll mod = 1e9 + 7; 11 12 ll n, x, y;

1219 骑士游历(棋盘DP)

1997年 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个整数x1,y1,x2,y2 输出描述 Output Descrip

【CODEVS1219】骑士游历

题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个整数x1,y1,x2,y2 输出描述 Output Description 输出方案数 样例输入 Sample Input 30 30 1 15 3 15 样例输出