写博客只为了巩固已学知识,如有问题欢迎大家指出。
关于基本线性dp,属于动态规划的一种,其解决问题的基本方法的通解一般为以下几点:
1.设计状态
2.写出状态转移方程(这个与递推有点相似)
3.确定初始状态(初始化数据)
4.执行状态转移
5.返回问题所需的解
下面用题目举例子说明
746. 使用最小花费爬楼梯 - 力扣(LeetCode)
第一题题解:
我们用一个数组来表示状态:f[i]表示爬到第i层楼梯的最小花费,由于每次只能爬1层或者2层楼梯,所以f[i]这个状态只能从f[i - 1]或者f[i -2]转移来,那么情况就可以分为两类
(1)假如从i- 1 层爬上来的话 , 那么所需的花费应当是f[i - 1] + cost[i - 1]
(2)假如从i- 2 层爬上来的话 , 那么所需的花费应当是f[i - 2] + cost[i - 2]
情况只有这两种,现在我们只需考虑最小花费的一种情况,就是这两种情况取小,然后我们就可以得到这个状态转移方程 f[i] = min ( f[i - 1] + cost[i - 1] , f[i - 2] + cost[i - 2]) 最后别忘了初始化数据f[0] f[1] ,起始条件可以任选楼梯 ,所以花费是f[0] = 0 f[1] = 0
附上AC代码:
int min(int a, int b){
return a < b ? a : b;
}
int minCostClimbingStairs(int* cost, int costSize){
int f[1001] = {0 , 0};
for(int i = 2 ; i <= costSize ; i++){
f[i] = min(f[i - 1] + cost[i - 1] , f[i -2] + cost[i -2]);
}
return f[costSize];
}
198. 打家劫舍 - 力扣(LeetCode)
第二题题解:
比第一题稍微难一点,但是题目思路还是差不多,都是寻找状态方程(这个是最重要的)
定义一个数组dp[i]表示:偷前 i 间房子能得到的最大值。
假设有 A B C D E 这几间房子 ,合法情况有如下两种:
(1)最后选择偷E房子,那么D肯定不能选 , 于是dp[E]最后的结果应当是dp[C],最后结果就是num[E] + dp[C]
(2)最后不选择偷E房子 , 那么最后情况就是dp[D]
在这两种间选择最大的 ,于是我们可以知道状态转移方程就是:
dp[i] = max ( dp[i - 1] , num[i ] + dp[i - 2])
同样的初始化别忘了 , 如果只有一间房子,那么可以直接返回num[0]. 若房子多于2间 ,那么dp[0] = num[0] dp[1] = max(num[0] , num[1])
附上AC代码:
int max(int a , int b){
return a > b ? a : b;
}
int rob(int* nums, int numsSize){
int dp[101];
if(numsSize == 1){
return nums[0];
}
dp[0] = nums[0];
dp[1] = max(nums[0] , nums[1]);
for(int i = 2 ; i < numsSize ; i++){
dp[i] = max(dp[i - 1] , nums[i] + dp[i - 2]);
}
return dp[numsSize - 1];
}
740. 删除并获得点数 - 力扣(LeetCode)

第三题题解:
这题如果不放在动态规划上我应该很难联系上来。
根据题意,在选择了元素 x 后,该元素以及所有等于 x−1或 x+1的元素会从数组中删去。若还有多个值为 x 的元素,由于所有等于 x−1 或 x+1 的元素已经被删除,我们可以直接删除 x并获得其点数。因此若选择了 x,所有等于 x 的元素也应一同被选择,以尽可能多地获得点数。我们可以直接把原数组的元素放进一个哈希表中去,然后直接对这个哈希表进行一个如同第二题的一个打家劫舍(这个题就是第二题打家劫舍的一个变式)
附上AC代码:
int hash[10001] , dp[10001];
int max(int a,int b){
return a > b ? a : b;
}
int deleteAndEarn(int* nums, int numsSize){
memset(hash , 0 , sizeof(hash));
for(int i = 0 ; i < numsSize ; i++){
hash[nums[i]] += nums[i];
}
dp[0] = 0;
dp[1] = hash[1];
for(int i = 2 ; i <= 10000 ; i++){
dp[i] = max(dp[i - 1] , dp[i - 2] + hash[i]);
}
return dp[10000];
}
文章介绍了动态规划中的线性DP方法,通过三个具体的LeetCode题目——最小花费爬楼梯、打家劫舍和删除并获得点数,阐述了解决这类问题的基本步骤:设计状态、状态转移方程、初始化和执行转移,最后返回解。每个题目都提供了AC代码示例,展示如何应用状态转移方程找到最优解。

497





