动态规划

动态规划

动态规划是一种算法思想,用于解决具有重叠子问题、最优子结构特征的问题。 重叠子问题:子问题是原问题的小版本
最优子结构:大问题的最优解包含小问题的最优解,通过小问题可以推导出大问题

楼梯有n个台阶,每次可以上1阶或2阶。一共有多少种不同的上楼方法?
原问题:n个台阶的上楼方案数
子问题:n-1个台阶的上楼方案数、n-2个台阶的上楼方案数、n-3个台阶的上楼方案数…
最优子结构:子问题的最优解能否推出原问题的最优解?
要走到第n级台阶,要么从n-1一步走过去,要么从n-2一步走过去,因此:
n个台阶的上楼方案数=n-1个台阶的上楼方案数+n-2个台阶的上楼方案数
无后效性:”未来与过去无关“,只需考虑当下如何走到第n级,不需要考虑先前如何走到第n-1、第n-2,直接利用结果计算即可,最优子结构满足无后效性。

  • 楼梯有n个台阶,每次可以一步上1阶、2阶、4阶。一共有多少种不同的上楼方法?
  • 楼梯有n个台阶,每次可以一步上1阶、k阶。一共有多少种不同的上楼方法?
  • 楼梯有n个台阶,每次可以一步上1阶、2阶、… 、k阶。一共有多少种不同的上楼方法?

动态规划分析步骤

拆分子问题:将原问题拆解成子问题,找到问题之间的联系。
确定状态:此处的”状态“代指不同的问题,例如dp[x]表示上x台阶的方案数,其中x就是状态;确定状态就是确定问题需要几个维度的已知变量。一般是“前n个xxx为m的最大价值/最小价值/方案数”等
状态转移方程:状态(子问题)之间是如何转移,即,一个状态由哪几个状态转移来,或者该状态可以转移到哪些状态上
实现:按照循环、记忆化搜索等方式求解最终状态(答案)。

3367破损的楼梯

题目链接:3367破损的楼梯
在这里插入图片描述
在计算台阶方案时,如果当前台阶是坏的,则需要跳过该台阶的状态更新
vis[x] = 1表示第x级台阶损坏

N = 100010
mod = 1000000007
#定义长度为N的数组vis和f,并将它们初始化为0
vis = [0] * N
f = [0] * N
#读取输入数据,包括楼的总级数n和坏掉的台阶数m,以及坏掉的台阶编号X
n , m = map(int , input().split())
X = list(map(int , input().split()))
#遍历坏掉的台阶编号X,将对应的vis数组位置设为1,表示该台阶已经坏了
for x in X:
    vis[x] = 1
#设置初始条件,即到达第0级台阶只有一种方法,即不迈步,所以f[0]赋值为1;
#到达第1级台阶有两种方法,要么不迈步,要么迈一步,所以f[1]赋值为1减去vis[1]的值
f[0] = 1
f[1] = 1 - vis[1]
'''
循环从第2级台阶开始遍历到第n级台阶。如果当前台阶已经坏了(vis[i]为真),则跳过当前迭代。
否则,计算到达当前台阶的方法数,即到达前一级台阶的方法数加上到达前两级台阶的方法数,并对结果取模。最后,输出到达第n级台阶的方法数。
'''
for i in range(2,n+1):
    if vis[i]:
        continue
    f[i] = (f[i-1] + f[i-2]) % mod
print(f[n])

运行结果

6 1
3

4

3423安全序列

题目链接:3423安全序列
在这里插入图片描述

# `dp[i]` 表示到达第 `i` 步的方案数

mod = 1000000007
n , k = map(int , input().split())
dp = [0] * (n+1)
# 初始状态:不放置也为一种方案
dp[0] = 1
for i in range(1,n+1):
    #判断当前位置 `i` 是否大于等于 `k+1`。
    #如果是,那么说明存在至少 `k+1` 个位置可以放置油桶,也就是说,可以从前 `i-k-1` 步的任何位置移动到第 `i` 步。
    if i-k-1 >= 0:
        #如果满足上述条件,那么可以从前 `i-1` 步和前 `i-k-1` 步的方案数之和得到第 `i` 步的方案数。
        #这是因为可以选择从前 `i-1` 步直接移动到第 `i` 步,也可以从前 `i-k-1` 步移动到第 `i` 步。然后对结果取模,防止结果过大。
        dp[i] = (dp[i-1] + dp[i-k-1]) % mod
    else:#没有足够的位置可以放置油桶,只能从前 `i-1` 步移动到第 `i` 步。
        #在这种情况下,方案数就是前 `i-1` 步的方案数加一。
        dp[i] = (dp[i-1] + 1) % mod
print(dp[n])

运行结果

4 2

6

参考链接:https://blog.csdn.net/Charlie482/article/details/136441362?spm=1001.2014.3001.5502

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

唐丶晚笙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值