DP专题——斐波那契数列和路径问题

DP专题——斐波那契数列和路径问题

斐波那契数列

1.定义:

斐波那契数列的定义如下:

  • F(0) = 0

  • F(1) = 1

    …….

  • F(n) = F(n-1) + F(n-2) (n ≥ 2)

2 .解法流程

我们可以看到,F(n)依赖F(n-1) 和 F(n-2),也就是第三个数依赖于他的前两个数。因此在此类问题中,我们常是建立一个dp表,根据状态转移方程来确定,怎么来填写这个表。通过存储子问题的解,来达到现问题的解。

(1) .状态表示: 常用dp[i], i 表示以某个位置结束或者开始,以[0,i] 区间上表示

(2) .状态转移方程(未填写表示因题而变)

(3) .初始化

(4) .填表顺序

(5) .返回值

3.例题

(1)
在这里插入图片描述
根据上诉思路,我们只需先求出 Tn-1 和 Tn-2 即可 ,代码如下:

class Solution {
public:
    int tribonacci(int n) {
        //1.创建dp表
        vector<int> tmp(n+1);
        //2.初始化
        if(n == 0)return 0;
        else if(n <= 2)return 1;
        tmp[0] = 0,tmp[1] = 1,tmp[2] = 1;
        //3.填表
        for(int i = 3; i <= n; i++)
        {
            tmp[i] = tmp[i-1]+tmp[i-2]+tmp[i-3];
        }
        //4.确定返回值
        return tmp[n];
    }
};

路径问题

1.解法流程

(1) .状态表示: 常用dp[i][j], [i][j] 表示从 [i, j] 位置出发,或者从起始位置出发,到达 [i, j] 位置

(2) .状态转移方程(未填写表示因题而变)

(3) .初始化 : 可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:

​ i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;

​ ii. 「下标的映射关系」。

(4) .填表顺序

(5) .返回值

2.例题

(1)
在这里插入图片描述

​ 这道题如果我们定义成:从起点开始,到达 [i, j] 位置的时候,所需的最低初始健康点数,此时会有个问题,那就是后面的路我不一定走的下去了,因为我们当前的健康点数还会受到后⾯的路径的影响,可能扣血会扣到不足以支撑我们继续走下去。
​ **所以这题我们最后定义为从 [i, j] 位置出发,到达终点时所需的最低健康点数。**从 [i, j] 位置出发,下⼀步会有两种选择:
​ i. ⾛到右边,然后⾛向终点
​ ii. ⾛到下边,然后⾛向终点
​ 上述分析可得,dp[i][j] = min(dp[i+1][j],dp[i][j+1]) - dungeon[i][j];
​ 但此时有个特殊情况需要我们处理,那就是如果dungeon[i][j]的值过大,也就是某个格子里的血包特别大,这会使dp[i][j]小于0,这一是不符合我们的定义,二是会影响别的位置的格子的值,所以我们在这里要特判

​ dp[i][j] = max(1,dp[i][j]);//防止当前dungeon[i][j]是一个超大的值,导致dp[i][j]里面存放的是负数

​ 代码如下:

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int m = dungeon.size(),n = dungeon[0].size();
        vector<vector<int>> dp(m+1,vector<int>(n+1,INT_MAX));
        //dp[i][j]表示,从i,j位置出发,到达终点,所需的最初始健康点数
        
        dp[m-1][n] = 1;//到达终点时骑士至少需要 1 点生命值。
        
        //dp[i][j]的值,等于下面和右边的dp的最小值,再减去当前dungeon[i][j]的值
        
        for(int i = m-1 ; i >= 0; i--)
            for(int j = n-1; j >= 0; j--)//从下往上,从右往左推
                {
                    dp[i][j] = min(dp[i+1][j],dp[i][j+1]) - dungeon[i][j];
                    dp[i][j] = max(1,dp[i][j]);//防止当前dungeon[i][j]是一个超大的值,导致dp[i][j]里面存放的是负数
                }
        return dp[0][0];    
     }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值