其他分享
首页 > 其他分享> > 动态规划--爬楼梯进阶版(爬楼梯+跳跃游戏+最少加油次数)

动态规划--爬楼梯进阶版(爬楼梯+跳跃游戏+最少加油次数)

作者:互联网

爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

任意取出一节台阶,思考:我们是怎么到这里来的呢?可能从下一阶上来,也有可能从下下一阶上来;再继续思考,我们是怎么从下一阶(下下一阶)上来的呢?结果同上;经此可以推导得出状态转移方程为:

初始化 num[1] = 1; num[2] = 2;
num[i] = num[i-1] + num[i-2];
class Solution {
public:
    int num[46];
    int climbStairs(int n) {
        if(n == 1)  return 1;
        if(n == 2)  return 2;
        int one_ = 0; int two_ = 0;
        if(num[n-1] == 0) num[n-1] = climbStairs(n-1);
        if(num[n-2] == 0) num[n-2] = climbStairs(n-2);
        num[n] = num[n-1] + num[n-2] ;
        return num[n];
    }
};

跳跃游戏Ⅱ

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

这道题相对于上一道题来说,改变的条件是每一格可以跳跃的步数。那么任意取一个台阶,它就可能是从之前的任意一个可以跳跃过来的台阶得来,那么到达这个格子的可能数的计算式为:

count[i] = min(count[i],count[j] + 1) 
(0 <= j <= i-1 && num[j] >= i - j)
class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        vector<int> count(len);
        count[0] = 0;
        for(int i = 1;i <= len-1 ;i++){
            count[i] = INT_MAX;
            for(int j = 0 ; j <= i-1 ;j++){
                if(nums[j] >= i - j )
                    count[i] = min(count[i],count[j]+1);
            }
        }
        return count[len-1];
    }
};

最低加油次数

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。

沿途有加油站,每个 station[i] 代表一个加油站,它位于出发位置东面 station[i][0] 英里处,并且有 station[i][1] 升汽油。

假设汽车油箱的容量是无限的,其中最初有 startFuel 升燃料。它每行驶 1 英里就会用掉 1 升汽油。

当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。

为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回 -1 。

注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。

输入:target = 1, startFuel = 1, stations = []
输出:0
解释:我们可以在不加油的情况下到达目的地。

输入:target = 100, startFuel = 1, stations = [[10,100]]
输出:-1
解释:我们无法抵达目的地,甚至无法到达第一个加油站。

相对于前两道题来说,这道题的不同之处在于:1.步数可以累加 2.点与点之间的距离由不变的1改为了可变 不过依然是求最小的停留次数。
简单对题意做一个转换将为了到达目的地,汽车所必要的最低加油次数 更改为 汽车最少需要加多少次油,才能积攒够到达终点的油量
那么状态转移方程就可以这样来设计:

//i代表的是站点,当循环结束之后 dp[i] 中所存储的就是在加油 i 次的前提下,所能够行进的最大公里数
        for (int i = 0; i < n; i++) {
//这里为什么要倒着遍历呢?
//为了确保每个dp[j+1] 的计算中,加油站stations[i] 只会被计算一次
            for (int j = i; j >= 0; j--) {
//如果说加油j次可以到达
                if (dp[j] >= stations[i][0]) { 
//就看看在station[i]处落脚是否可以使可行驶的距离更远
                    dp[j + 1] = max(dp[j + 1], dp[j] + stations[i][1]);
                }
            }
        }
class Solution {
public:
    int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
        int n = stations.size();
        vector<long> dp(n + 1);
        dp[0] = startFuel;
        for (int i = 0; i < n; i++) {
            for (int j = i; j >= 0; j--) {
                if (dp[j] >= stations[i][0]) {
                    dp[j + 1] = max(dp[j + 1], dp[j] + stations[i][1]);
                }
            }
        }
        for (int i = 0; i <= n; i++) {
            if (dp[i] >= target) {
                return i;
            }
        }
        return -1;
    }
};

标签:count,爬楼梯,进阶,stations,--,到达,int,num,dp
来源: https://www.cnblogs.com/wuqiu/p/16438917.html