table of Contents
Topic:. 935 Knight Dialer Dialer Knight
Problem Description
Chess knight move can press shown below:
This time, we will "knight" in any number key telephone dial pad (shown above), the next hop will knight N-1 step. Each step must be the number keys to jump from one to another number key.
Whenever it falls on a key (including the initial position of the knight), are allocated corresponding to the numeric key, a total of N-bit digital press.
You can use this way how many different numbers dialed?
Because the answer may be large, so the output answer mode 10 ^ 9 + 7 .
Example 1:
Input: 1
Output: 10Example 2:
Input: 2
Output: 20Example 3:
Input: 3
Output: 46prompt:
1 <= N <= 5000
Ideas 1
First, we look at the knight to walk on the dialpad
Thought the use of dynamic programming, are each a result of a computation obtained by the above (except for the first round)
Algorithm
- Not by OJ
- The idea is correct, limited data types, obtaining greater value will overflow
class Solution {
public int knightDialer(int N) {
if (N == 1) return 10;
// 第二轮 每个键位下一步数
int[] jumpSizes = {2,2,2,2,3,0,3,2,2,2};
// 临时存放 运算的值
int[] tempSizes = new int[10];
// 从底层开始 推理出顶层的答案
for (int i = 2; i < N; i++) {
giveNum(tempSizes,0, jumpSizes, 4, 6);
giveNum(tempSizes,1, jumpSizes, 6, 8);
giveNum(tempSizes,2, jumpSizes, 7, 9);
giveNum(tempSizes,3, jumpSizes, 4, 8);
giveNum(tempSizes,4, jumpSizes, 3, 9, 0);
giveNum(tempSizes,6, jumpSizes, 1, 7, 0);
giveNum(tempSizes,7, jumpSizes, 2, 6);
giveNum(tempSizes,8, jumpSizes, 1, 3);
giveNum(tempSizes,9, jumpSizes, 2, 4);
tempSizes[5] = 0;
// 更新当前轮次的结果
jumpSizes = Arrays.copyOf(tempSizes, 10);
}
int sum = 0;
for (int num : jumpSizes) sum += num;
return sum;
}
void giveNum(int[] dest, int i, int[] src, int j, int k) {
dest[i] = src[j] + src[k];
}
void giveNum(int[] dest, int i, int[] src, int j, int k, int p) {
dest[i] = src[j] + src[k] + src[p];
}
}
- By OJ
- Process is the same, but changing the type of data , plus modulo
class Solution {
int mod = 1000000007;
public int knightDialer(int N) {
if (N == 1) return 10;
// 将int改为long 数据不会溢出
long[] jumpSizes = {2,2,2,2,3,0,3,2,2,2};
long[] tempSizes = new long[10];
long sum = 0;
for (int i = 2; i < N; i++) {
giveNum(tempSizes,0, jumpSizes, 4, 6);
giveNum(tempSizes,1, jumpSizes, 6, 8);
giveNum(tempSizes,2, jumpSizes, 7, 9);
giveNum(tempSizes,3, jumpSizes, 4, 8);
giveNum(tempSizes,4, jumpSizes, 3, 9, 0);
giveNum(tempSizes,6, jumpSizes, 1, 7, 0);
giveNum(tempSizes,7, jumpSizes, 2, 6);
giveNum(tempSizes,8, jumpSizes, 1, 3);
giveNum(tempSizes,9, jumpSizes, 2, 4);
tempSizes[5] = 0;
jumpSizes = Arrays.copyOf(tempSizes, 10);
}
for (long num : jumpSizes) sum += num;
return (int)(sum%mod);
}
void giveNum(long[] dest, int i, long[] src, int j, int k) {
// 每次求和后 都进行取模
dest[i] = (src[j] + src[k]) % mod;
}
void giveNum(long[] dest, int i, long[] src, int j, int k, int p) {
dest[i] = (src[j] + src[k] + src[p]) % mod;
}
}
Ideas 2
By observing the position of all the buttons and the calculation of the trajectory, summed Law
Algorithm
class Solution {
public int knightDialer(int N) {
if (N == 1) return 10;
int mod = 1000000007;
// a表示四角的和
// b表示中部左右的和
// c表示中部上下的和
// d表示0键位的值
long a = 4, b = 2, c = 2, d = 1;
for (int i = 1; i < N; i++) {
long A = (2*(b+c)) % mod;
long B = (a + 2*d) % mod;
c = a;
d = b;
a = A;
b = B;
}
return (int)((a+b+c+d)%mod);
}
}