10.25-10.31周博客

动态规划:
dp一般用于解决多阶段决策问题。每个阶段都要做一个决策,全部的决策组成一个决策序列,要你求一个最好的决策序列使得这个问题有最优解
一、适用动态规划解决的问题:
1.计数问题:解决问题有多少种方案
2.优化问题:求最大值或最小值问题
二、使用DP的要求
1.最优子结构
2.重复子问题:求解子问题时,会出现重复计算(overlapping)。如果没有重复计算,则退化成分治算法(divide and conquer)
3.无后效性:调用子问题最优解时,子问题的最优解不发生改变。
三、动态规划的使用方法:
1.将待求解的问题分为若干个重复子问题
2.只在第一次出现子问题的时候求解,将这个子问题的结果保存
3.在后面遇到这类子问题的时候,直接调用前面子问题的结果
四、动态规划的应用
力扣746题:使用最小花费爬楼梯
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-cost-climbing-stairs
思路:
爬上第i个阶梯有两种方法:
1.从第i-2个阶梯走两步到第i个阶梯,对应的体力花费为dp[i-2]+cost[i]
2.从第i-1个阶梯走一步到第i个阶梯,对应的体力花费为dp[i-1]+cost[i]
3.每上一步阶梯,都可以视作一个子问题,最优子问题的解dp[i]=min(dp[i-2],dp[i-1])+cost[i]
解题代码:
int minCostClimbingStairs(int* cost, int costSize){
int dp = (int)malloc(sizeof(int) * costSize);
dp[0] = cost[0];
dp[1] = cost[1];
int i;
for(i = 2;i < costSize;i++){
if(dp[i - 2] < dp[i - 1]){//判断是从i-2还是从i-1到i花费的体力更少
dp[i] = dp[i - 2] + cost[i];
}
else
dp[i] = dp[i -1] + cost[i];
}
if(dp[costSize - 2] < dp[costSize - 1])
return dp[costSize - 2];
else
return dp[costSize - 1];
}
因为只用到了前两步的结果,可将代码简化为如下:
class Solution {
public int minCostClimbingStairs(int[] cost) {
for(int i = 2;i < cost.length;i++){
cost[i] = Math.min(cost[i - 2],cost[i - 1]) + cost[i];
}
return Math.min(cost[cost.length - 1],cost[cost.length - 2]);
}
}

力扣509题:斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n) 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fibonacci-number
思路:
从F(2)开始,每个数都是它的前两位数之和,符合动态规划的思想
解题代码:
int fib(int n){
if(n == 0)
return 0;
if(n == 1)
return 1;
int dp = (int)malloc(sizeof(int) * (n + 1));
dp[0] = 0;
dp[1] = 1;
int i;
for(i = 2;i <= n;i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}

因为只用到了前两个子问题的解,代码简化为:
class Solution {
public int fib(int n) {
if(n < 2)
return n;
int a = 0,b = 1,c;
for(int i = 2;i <= n;i++){
c = a +b;
a = b;
b = c;
}
return b;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值