zoukankan      html  css  js  c++  java
  • 935. Knight Dialer

    A chess knight can move as indicated in the chess diagram below:

     .           

    This time, we place our chess knight on any numbered key of a phone pad (indicated above), and the knight makes N-1 hops.  Each hop must be from one key to another numbered key.

    Each time it lands on a key (including the initial placement of the knight), it presses the number of that key, pressing N digits total.

    How many distinct numbers can you dial in this manner?

    Since the answer may be large, output the answer modulo 10^9 + 7.

    Example 1:

    Input: 1
    Output: 10
    

    Example 2:

    Input: 2
    Output: 20
    

    Example 3:

    Input: 3
    Output: 46

    Note:

    • 1 <= N <= 5000

    Approach #1: DP. [Java]

    class Solution {
        public int knightDialer(int N) {
            int mod = 1000000007;
            int[][][] dp = new int[N+1][5][4];
    
            for (int j = 0; j < 4; ++j)
                for (int k = 0; k < 3; ++k)
                    dp[1][j][k] = 1;
            dp[1][3][0] = dp[1][3][2] = 0;
            int[][] dirs = {{1, 2}, {1, -2}, {2, 1}, {2, -1},
                              {-1, 2}, {-1, -2}, {-2, 1}, {-2, -1}};
    
            for (int k = 2; k <= N; ++k) {
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 3; ++j) {
                        if (i == 3 && j != 1) continue;
                        for (int d = 0; d < 8; ++d) {
                            int x_ = i + dirs[d][0];
                            int y_ = j + dirs[d][1];
                            if (x_ < 0 || y_ < 0 || x_ >= 4 || y_ >= 3) continue;
                            dp[k][i][j] = (dp[k][i][j] + dp[k-1][x_][y_]) % mod;
                        }
                    }
                }
            }
            
            int ans = 0;
            for (int i = 0; i < 4; ++i) {
                for (int j = 0; j < 3; ++j) {
                    ans = (ans + dp[N][i][j]) % mod;
                    // System.out.print(dp[N][i][j] + "  ");
                }
                // System.out.println("ans = " + ans);
            }
            
            return ans;
        }
    }
    

    Analysis:

    We can define dp[k][i][j] as of ways to dial and the last key is (i, j) after k steps

    Note: dp[*][3][0], dp[*][3][2] are always zero for all the steps.

    Init: dp[0][i][j] = 1

    Transition: dp[k][i][j] = sum(dp[k-1][i+dy][j+dx]) 8 ways of move from last step.

    ans = sum(dp[k])

    Time complexity: O(kmn) or O(k*12*8) = O(k)

    Space complexity: O(kmn) -> O(12 * 8) = O(1)

      

    Approach #2: DP. [C++]

    class Solution {
    public:
        int knightDialer(int N) {
            vector<vector<int>> dp(4, vector<int>(3, 1));
            dp[3][0] = dp[3][2] = 0;
            int mod = pow(10, 9) + 7;
            vector<pair<int, int>> dirs = {{1, 2}, {1, -2}, {2, 1}, {2, -1},
                                           {-1, 2}, {-1, -2}, {-2, 1}, {-2, -1}};
            for (int k = 2; k <= N; ++k) {
                vector<vector<int>> temp(4, vector<int>(3, 0));
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 3; ++j) {
                        if (i == 3 && j != 1) continue;
                        for (int k = 0; k < 8; ++k) {
                            int x_ = i + dirs[k].first;
                            int y_ = j + dirs[k].second;
                            if (x_ < 0 || y_ < 0 || x_ >= 4 || y_ >= 3) continue;
                            temp[i][j] = (temp[i][j] + dp[x_][y_]) % mod;
                        }
                    }
                }
                dp.swap(temp);
            }
            
            int ans = 0;
            for (int i = 0; i < 4; ++i) {
                for (int j = 0; j < 3; ++j) {
                    ans = (ans + dp[i][j]) % mod;
                }
            }
            
            return ans;
        }
    };
    

      

    define dp[k][i] as of ways to dial and the last key is i after k steps

    init: dp[0][0:10] = 1

    translation: dp[k][i] = sum(dp[k-1][j]) that j  can move to i

    ans: sum(dp[k])

    Time complexity: O(k*10) = O(k)

    Space complexity: O(k*10) -> O(10) = O(1).

    Reference:

    https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-935-knight-dialer/

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    vbox下安装centos (全部都是基于64位)
    用php获取js变量的值
    IOS开发帐号与发布问题综合
    深入理解那该死的BOM
    xcode的svn和git使用方法
    编程中神秘的引号(重要)
    photoshop cs6 Mac版本
    开源免费天气预报接口API以及全国所有地区代码!
    [C语言] 数据结构-预备知识指针
    [PHP] apache在worker模式配置fastcgi使用php-fpm
  • 原文地址:https://www.cnblogs.com/h-hkai/p/10611152.html
Copyright © 2011-2022 走看看