leetcode935. 骑士拨号器

题目大意

国际象棋中的骑士可以按下图所示进行移动:

在这里插入图片描述
在这里插入图片描述

这一次,我们将 “骑士” 放在电话拨号盘的任意数字键(如上图所示)上,接下来,骑士将会跳 N-1 步。每一步必须是从一个数字键跳到另一个数字键。

每当它落在一个键上(包括骑士的初始位置),都会拨出键所对应的数字,总共按下 N 位数字。

你能用这种方式拨出多少个不同的号码?

因为答案可能很大,所以输出答案模 10^9 + 7。

示例

输入:2
输出:20

解题思路

首先写递归,当N=1时,只有一种答案,即当前数字;否则,我可以从当前数字按规则跳到下一个数字,且N=N-1;

class Solution {
public:
    int knightDialer(int N) {
    	int res = 0;
    	for (int i = 0; i <= 9; ++i){
    		res += dfs(N, i);
    	}
    	return res;
    }

    int dfs(int N, int curIndex){
    	if (N == 1)
    		return 1;

    	if (curIndex == 0)
    		return dfs(N - 1, 4) + dfs(N - 1, 6);
    	else if (curIndex == 1)
    		return dfs(N - 1, 6) + dfs(N - 1, 8);
    	else if (curIndex == 2)
    		return dfs(N - 1, 7) + dfs(N - 1, 9);
    	else if (curIndex == 3)
    		return dfs(N - 1, 4) + dfs(N - 1, 8);
    	else if (curIndex == 4)
    		return dfs(N - 1, 3) + dfs(N - 1, 9) + dfs(N - 1, 0);
    	else if (curIndex == 5)
    		return 0;
    	else if (curIndex == 6)
    		return dfs(N - 1, 1) + dfs(N - 1, 7) + dfs(N - 1, 0);
    	else if (curIndex == 7)
    		return dfs(N - 1, 2) + dfs(N - 1, 6);
    	else if (curIndex == 8)
    		return dfs(N - 1, 1) + dfs(N - 1, 3);
    	else
    		return dfs(N - 1, 2) + dfs(N - 1, 4);
    }
};

将上述递归转为动态规划:

class Solution {
public:
    int knightDialer(int N) {
    	vector<vector<int>> dp(N, vector<int>(10, 0));

    	for (int i = 0; i < 10; ++i)
    		dp[0][i] = 1;

    	for (int i = 1; i < N; ++i){
    		for (int j = 0; j < 10; ++j){
    			if (j == 0){
    				dp[i][j] = (dp[i - 1][4] + dp[i - 1][6]) % 1000000007;
    			}
    			else if (j == 1)
    				dp[i][j] = (dp[i - 1][6] + dp[i - 1][8]) % 1000000007;
    			else if (j == 2)
    				dp[i][j] = (dp[i - 1][7] + dp[i - 1][9]) % 1000000007;
    			else if (j == 3)
    				dp[i][j] = (dp[i - 1][4] + dp[i - 1][8]) % 1000000007;
    			else if (j == 4)
    				dp[i][j] = ((dp[i - 1][0] + dp[i - 1][3]) % 1000000007 + dp[i - 1][9]) % 1000000007;
    			else if (j == 6)
    				dp[i][j] = ((dp[i - 1][0] + dp[i - 1][1]) % 1000000007 + dp[i - 1][7]) % 1000000007;
    			else if (j == 7)
    				dp[i][j] = (dp[i - 1][2] + dp[i - 1][6]) % 1000000007;
    			else if (j == 8)
    				dp[i][j] = (dp[i - 1][1] + dp[i - 1][3]) % 1000000007;
    			else if (j == 9)
    				dp[i][j] = (dp[i - 1][2] + dp[i - 1][4]) % 1000000007;
    		}
    	}
    	int res = 0;
    	for (int i = 0; i < 10; ++i)
    		res = (res + dp[N - 1][i]) % 1000000007;
    	return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值