MATLAB 动态规划

26 篇文章 0 订阅
20 篇文章 12 订阅

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。
🍎个人主页:小嗷犬的个人主页
🍊个人网站:小嗷犬的技术小站
🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。



什么是动态规划

动态规划是一种数学优化方法,它是一种在给定约束条件下,求解最优化问题的方法。动态规划的基本思想是将原问题分解为若干个子问题,先求解子问题的最优解,然后根据子问题的最优解,求解原问题的最优解。

动态规划的步骤通常为:

  1. 将原问题分解为子问题
  2. 确定状态
  3. 确定一些初始状态(边界状态)的值
  4. 确定状态转移方程

思想上类似于递归,但动态规划采用记录子问题的最优解的方法,避免了重复计算子问题的最优解,从而提高了计算效率;除此之外,动态规划通常采用自底向上的方法,而递归通常采用自顶向下的方法。


斐波那契数列

斐波那契数列作为递归算法的经典教学案例也可以用动态规划来解决,并且效率更高。

递归算法

function f = fib(n)
    if n == 1 || n == 2
        f = 1;
    else
        f = fib(n-1) + fib(n-2);
    end
end

计算 fib(40)

>> tic; fib(40); toc
历时 9.110819 秒。

计算 fib(400)

>> tic; fib(100); toc
% 超过5分钟,主动停止

动态规划算法

function f = fib(n)
    f = zeros(1, n);
    f(1) = 1;
    f(2) = 1;
    for i = 3:n
        f(i) = f(i-1) + f(i-2);
    end
    f = f(n);
end

计算 fib(40)

>> tic; fib(40); toc
历时 0.000180 秒。

计算 fib(400)

>> tic; fib(400); toc
历时 0.003652 秒。

以上时间数据仅为单次执行得出的结果,可能具有一定的随机性,但是我们仍能看出,动态规划算法的效率要远远高于递归算法。


跳台阶

跳台阶问题描述如下:

有一个台阶,一次可以跳1级或2级,求跳上n级台阶有多少种跳法。

解题思路:

类似于斐波那契数列,我们可以用动态规划来解决这个问题。

  1. 将原问题分解为子问题:跳上n级台阶的跳法数 = 跳上n-1级台阶的跳法数 + 跳上n-2级台阶的跳法数
  2. 确定状态:设跳上n级台阶的跳法数为f(n)
  3. 确定一些初始状态(边界状态)的值:f(1) = 1, f(2) = 2
  4. 确定状态转移方程:f(n) = f(n-1) + f(n-2)

动态规划代码实现:

function f = jump(n)
    f = zeros(1, n);
    f(1) = 1;
    f(2) = 2;
    for i = 3:n
        f(i) = f(i-1) + f(i-2);
    end
    f = f(n);
end

计算 jump(100)

>> tic; jump(100); toc
历时 0.001638 秒。

接雨水

题目链接:LeetCode 42 题:接雨水

题目描述:

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例1:
接雨水

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

示例2:

输入:height = [4,2,0,3,2,5]
输出:9

解题思路:

  1. 将原问题分解为子问题:对于每个柱子,能接的雨水量 = min(当前柱子及其左边最高柱子高度, 当前柱子及其右边最高柱子高度) - 当前柱子高度;第i个柱子及其左边最高柱子高度 = max(第i-1个柱子左边最高柱子高度, 第i个柱子高度),当前柱子及其右边最高柱子高度同理。
  2. 确定状态:设当前柱子及其左边最高柱子高度为leftMax[i],当前柱子及其右边最高柱子高度为rightMax[i]。
  3. 确定一些初始状态(边界状态)的值:leftMax[1] = height[1],rightMax[n] = height[n]。
  4. 确定状态转移方程:leftMax[i] = max(leftMax[i-1], height[i]),rightMax[i] = max(rightMax[i+1], height[i])。

接雨水题解

动态规划代码实现:

function r = rain(height)
    n = length(height);
    leftMax = zeros(1, n);
    rightMax = zeros(1, n);
    leftMax(1) = height(1);
    rightMax(n) = height(n);
    for i = 2:n
        leftMax(i) = max(leftMax(i-1), height(i));
        rightMax(n-i+1) = max(rightMax(n-i+2), height(n-i+1));
    end
    r = sum(min(leftMax, rightMax) - height);
end

计算 rain([0,1,0,2,1,0,1,3,2,1,2,1])

>> tic; rain([0,1,0,2,1,0,1,3,2,1,2,1]); toc
历时 0.005192 秒。
  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嗷犬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值