Description
The chess knight has a unique movement, it may move two squares vertically and one square horizontally, or two squares horizontally and one square vertically (with both forming the shape of an L). The possible movements of chess knight are shown in this diagaram:
A chess knight can move as indicated in the chess diagram below:
We have a chess knight and a phone pad as shown below, the knight can only stand on a numeric cell (i.e. blue cell).
Given an integer n, return how many distinct phone numbers of length n we can dial.
You are allowed to place the knight on any numeric cell initially and then you should perform n - 1 jumps to dial a number of length n. All jumps should be valid knight jumps.
As the answer may be very large, return the answer modulo 109 + 7.
Example 1:
Input: n = 1
Output: 10
Explanation: We need to dial a number of length 1, so placing the knight over any numeric cell of the 10 cells is sufficient.
Example 2:
Input: n = 2
Output: 20
Explanation: All the valid number we can dial are [04, 06, 16, 18, 27, 29, 34, 38, 40, 43, 49, 60, 61, 67, 72, 76, 81, 83, 92, 94]
Example 3:
Input: n = 3
Output: 46
Example 4:
Input: n = 4
Output: 104
Example 5:
Input: n = 3131
Output: 136006598
Explanation: Please take care of the mod.
Constraints:
- 1 <= n <= 5000
分析
题目的意思是:给定一个n,求在电话拨号上面组成n个数字的组合数,并且对拨号进行了限制,只能按照国际象棋那种方式选择下一个拨号数。这道题我参考了一下别人的思路,
根据题目中的规则我们可以得到下面的递推公式
f(1, n) = f(6, n-1) + f(8, n-1)
f(2, n) = f(7, n-1) + f(9, n-1)
f(3, n) = f(4, n-1) + f(8, n-1)
.....
令dp[i]= f(i, n),如果用字典来存放这些递推公式,那么遍历字典就能够求出dp了。
-
首先对于每个数字,他的下一个拨号数都是确定的,所以可以用一个字典存下来。
-
然后初始化一个dp数组,初始化为1,总共是10,表示第一次拨号只有10种啦。
-
对于选定了第一个数,接下来的走法就有很多了,因此可以遍历字典把走法算出来,最后求dp的总数就是最终的结果了。
当然我也做不出来,学习一下啦,哈哈。
代码
class Solution:
def knightDialer(self, n: int) -> int:
d={1:[6,8],2:[7,9],3:[4,8],4:[3,9,0],5:[],6:[1,7,0],7:[2,6],8:[3,1],9:[4,2],0:[4,6]}
dp=[1]*10
for i in range(n-1):
nxt=[0]*10
for k,v in d.items():
for num in v:
nxt[num]+=dp[k]
dp=nxt
return sum(dp)%(10**9+7)
参考文献
[LeetCode] 9-line Python DP
[动态规划]leetcode 935 Knight Dialer