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/

posted @ 2019-03-27 21:51  Veritas_des_Liberty  阅读(334)  评论(0编辑  收藏  举报