[Leetcode][动态规划] 第935题 骑士拨号器

本文探讨了在电话拨号盘上使用国际象棋骑士移动规则来生成不同号码的算法。通过动态规划方法,定义状态并进行转移,最终求解在N步内可生成的不同号码数量,结果取模10^9+7。

 

一、题目描述

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

 

                         

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

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

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

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

示例 1:

输入:1
输出:10

示例 2:

输入:2
输出:20

示例 3:

输入:3
输出:46

二、题目分析

1)动态规划。状态定义:dp[i][j]代表从j开始跳i步的可能性
2)辅助条件:建立一个map<int,vector<int>>,代表谁经过一步能跳到j位置

3)初始化dp[0][0-9]=1;

4)状态转移:dp[i][j]+=dp[i-1][mp[j][k]],0<=k<=mp[j].size()-1;

5)结果:sum(dp[n-1][0-9])

三、代码实现

 

class Solution {
public:
    int knightDialer(int N) {
        if (!N)return 10;
        vector <vector<int>>dp(N, vector<int>(10));
        int i, j, k;
        int Max = pow(10, 9) + 7;
        for (i = 0; i < 10; ++i) {
            dp[0][i] = 1;
        }
        map<int, vector<int>>mp;
        mp.insert({ 0,{ 4,6 } }), mp.insert({ 1,{ 6,8 } }), mp.insert({ 2,{ 7,9 } }), mp.insert({ 3,{ 4,8 } }), mp.insert({ 4,{ 0,3,9 } });
        mp.insert({ 5,{} }), mp.insert({ 6,{ 0,1,7 } }), mp.insert({ 7,{ 2,6 } }), mp.insert({ 8,{ 1,3, } }), mp.insert({ 9,{ 2,4 } });
        for (i = 1; i < N; ++i) {
            for (j = 0; j <= 9; ++j) {
                for (k = 0; k < mp[j].size(); ++k) {
                    dp[i][j] += dp[i - 1][mp[j][k]];
                    if (dp[i][j] > Max)
                        dp[i][j] = dp[i][j] % Max;
                }
            }
        }
        int sum = 0;
        for (int i = 0; i <=9; ++i) {
            sum += dp[N - 1][i];
            if (sum > Max)sum %= Max;
        }
        return sum;
    }
};

转载于:https://www.cnblogs.com/zhizhiyu/p/10152823.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值