动态规划--爬楼梯进阶版(爬楼梯+跳跃游戏+最少加油次数)
作者:互联网
爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 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