935. Knight Dialer
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
方法1: dynamic programming
huahua: https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-935-knight-dialer/
思路:
参考688。思路一致,但是有细节差别:1. 左下和右下两个格子是不能走的,2. 初始化的时候将除了这两个格子以外的点都设为1。换句话说,题目没有规定起始点在哪里,我们需要尝试所有的起点并求和。那么在dp里将所有可能的起点设为1, 同步求和就可以。另外由于数字很大,可以在每一次累加的时候都对constexpr求modulo,保持上限。
Complexity
Time complexity: O(N)
Space complexity: O(1)
class Solution {
public:
int knightDialer(int N) {
constexpr int kMod = 1e9 + 7;
int dirs[8][2] = {{1, 2}, {-1, -2}, {1, -2}, {-1, 2},
{2, 1}, {-2, -1}, {2, -1}, {-2, 1}};
vector<vector<int>> dp(4, vector<int>(3, 1));
dp[3][0] = dp[3][2] = 0;
for (int k = 1; k < N; k++){
vector<vector<int>> tmp(4, vector<int>(3, 0));
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
for (auto dir: dirs) {
int x = i + dir[0];
int y = j + dir[1];
if (x < 0 || x >= 4 || y < 0 || y >= 3 || x == 3 && y == 0 || x == 3 && y == 2) continue;
tmp[x][y] = (tmp[x][y] + dp[i][j]) % kMod;
}
}
}
swap(dp, tmp);
}
int result = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
result = (result + dp[i][j]) % kMod;
}
}
return result;
}
};