【算法】动态规划专题① ——线性DP python

ops/2025/2/1 8:33:01/

目录

  • 引入
  • 简单实现
  • 稍加变形
  • 举一反三
  • 实战演练
  • 总结


引入


楼梯有个台阶,每次可以一步上1阶或2阶。一共有多少种不同的上楼方法?

怎么去思考?
假设就只有1个台阶,走法只有:1
只有2台阶: 1+1,2
只有3台阶: 1+2, 1+1+1 ,2+1
只有4台阶: 1+1+2 ,2+2 , 1+2+1 ,1+1+1+1,2+1+1
不难观察到
3台阶的走法可以表示为1台阶的走法再+2,2台阶的走法+1
4台阶的走法可以表示为2台阶的走法再+2,3台阶的走法+1
自然递推出:
n台阶的走法可以表示为n-2台阶的走法再+2,n-1台阶的走法+1


解决步骤:
1.定义状态:
设dp[n]表示到达第n级台阶的不同方法总数。
2.状态转移方程:
因为每次只能走1步或2步,所以到达第n级台阶的方法数等于到达第(n-1)级台阶的方法数加上到达第(n-2)级台阶的方法数。
dp[n]=dp[n-1]+dp[n-2]
3.初始化:
当n=0时,没有台阶,认为有一种方法(什么都不做),因此dp[0]=1。
当n=1时,只有一种方法,即直接走上第一级台阶,所以dp[1]=1。
4.计算顺序:从低到高依次计算每一级台阶的方法数直到n。



简单实现


跳台阶 https://www.acwing.com/problem/content/823/

一个楼梯共有 n n n 级台阶,每次可以走一级或者两级,问从第 0 0 0 级台阶走到第 n n n 级台阶一共有多少种方案。

输入格式

共一行,包含一个整数 n n n

输出格式

共一行,包含一个整数,表示方案数。

数据范围

1 ≤ N ≤ 15 1\leq N\leq15 1N15

输入样例:

5

输出样例:

8

代码如下(示例):
python">n = int(input())
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):dp[i] = dp[i - 1] + dp[i - 2]
print(dp[n])


稍加变形


哎,就是玩 给你几个楼梯弄坏

破损的楼梯 https://www.lanqiao.cn/problems/3367/learning/?page=1&first_category_id=1&problem_id=3367

在这里插入图片描述

思路:

用vis数组标记不能走的台阶即可


题解code:

python">mod = 1000000007
n, m = map(int, input().split())
a = list(map(int, input().split()))
dp = [0] * (n + 1)
dp[0] = 1
vis = [0] * (n + 1)
for i in a:vis[i] = 1
for i in range(1, n + 1):if vis[i] == 0:dp[i] = (dp[i - 1] + dp[i - 2]) % mod
print(dp[n])


举一反三


每次可以走一级或者两级或者三级,一共有多少种方案呢?
测试链接 https://www.acwing.com/problem/content/3646/


每次可以向上迈 1∼K 级台阶,答案又是多少呢?
在这里我们给出1-k级台阶的解法


台阶问题 https://www.luogu.com.cn/problem/P1192

题目描述

N N N 级台阶,你一开始在底部,每次可以向上迈 1 ∼ K 1\sim K 1K 级台阶,问到达第 N N N 级台阶有多少种不同方式。

输入格式

两个正整数 N , K N,K N,K

输出格式

一个正整数 a n s ( m o d 100003 ) ans\pmod{100003} ans(mod100003),为到达第 N N N 级台阶的不同方式数。

样例输入

5 2

样例输出

8

提示

  • 对于 20 % 20\% 20% 的数据, 1 ≤ N ≤ 10 1\leq N\leq10 1N10 1 ≤ K ≤ 3 1\leq K\leq3 1K3
  • 对于 40 % 40\% 40% 的数据, 1 ≤ N ≤ 1000 1\leq N\leq1000 1N1000
  • 对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 100000 1\leq N\leq100000 1N100000 1 ≤ K ≤ 100 1\leq K\leq100 1K100

思路分析:

结合上面所学,不难得出:
dp[ i i i] = dp[ i i i - 1] + dp[ i i i - 2] + ······ +dp[ i i i - k k k]
当然,这是 i ≥ k i\geq k ik的情况
对于 i < k i< k i<k:
dp[ i i i] = dp[ i i i - 1] + dp[ i i i - 2] + ······ +dp[0]

题解code

python">mod = 100003n, k = map(int, input().split())
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):res = 0for j in range(min(i, k) + 1):res += dp[i - j]dp[i] = res % mod
print(dp[n])


结合前缀和能更快得出答案
什么?还不会前缀和?
点此跳转 超细致讲解


code:

python">mod = 100003
n, k = map(int, input().split())
dp = [0] * (n + 1)
dp[0] = 1
pre_sum = [0] * (n + 2)
pre_sum[1] = 1
for i in range(1, n + 1):if i <= k:dp[i] = pre_sum[i] % modelse:dp[i] = (pre_sum[i] - pre_sum[i - k]) % modpre_sum[i + 1] = (pre_sum[i] + dp[i]) % mod
print(dp[n])



实战演练


安全序列 https://www.lanqiao.cn/problems/3423/learning/?page=1&first_category_id=1&problem_id=3423

在这里插入图片描述

思路分析:

只有一个空位,那么只有 {0},{1}两种放法
两个空位,那么在上面的基础上放0或者隔k个0放1
{0,0},{1,0},{0,1}
三个空位,直接放0,或者隔k个0放1
{0,0,0} ,{1,0,0},{0,1,0}, {0,0,1}
四个空位,继续递推
{0,0,0,0} {1,0,0,0} {0,1,0,0} {0,0,1,0} {0,0,0,1} {1,0,0,1}
得到递推公式:
写出状态转移方程:
dp[ i i i] = dp[ i i i-1](后面直接放0)+ dp[ i i i- k k k-1](隔k个0后放1)


题解code:

python">mod = 1000000007
n, k = map(int, input().split())
dp = [0] * (n + 1)
dp[0] = 1
for i in range(1, n + 1):if i - k - 1 >= 0:dp[i] = (dp[i - k - 1] + dp[i - 1]) % modelse:dp[i] = (1 + dp[i - 1]) % mod
print(dp[n])


总结


线性动态规划(Linear Dynamic Programming, 简称线性DP)是一种动态规划的类型,它主要处理具有线性结构的问题。
在这种问题中,通常会有一个或多个序列作为输入,而解决这些问题的目标是找到满足某些条件的最优解。
线性DP问题的特点是可以将问题分解为若干个子问题,每个子问题仅涉及原问题的一个连续子序列,并且这些子问题之间存在重叠和递推关系。

本篇博客从台阶问题入手,逐步复杂化,帮助更好地理解一维线性DP


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢


http://www.ppmy.cn/ops/154695.html

相关文章

计算机毕业设计Django+Tensorflow音乐推荐系统 机器学习 深度学习 音乐可视化 音乐爬虫 知识图谱 混合神经网络推荐算法 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

科家多功能美发梳:科技赋能,重塑秀发新生

在繁忙的都市生活中,头皮健康与秀发养护成为了现代人不可忽视的日常课题。近日,科家电动按摩梳以其卓越的性能和创新设计,赢得了广大消费者的青睐。这款集科技与美学于一身的美发梳,不仅搭载了2亿负离子、6000次/分钟的声波振动等前沿技术,更融入了650nm聚能环红光与415nm强劲蓝…

蓝桥杯python语言基础(1)——编程基础

目录 一、python开发环境 二、python输入输出 &#xff08;1&#xff09;print输出函数 print(*object&#xff0c;sep,end\n,......) &#xff08;2&#xff09;input输入函数 input([prompt]), 输入的变量均为str字符串类型&#xff01; input()会读入一整行的信息 ​编…

JVM_程序计数器的作用、特点、线程私有、本地方法的概述

①. 程序计数器 ①. 作用 (是用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令) ②. 特点(是线程私有的 、不会存在内存溢出) ③. 注意:在物理上实现程序计数器是在寄存器实现的,整个cpu中最快的一个执行单元 ④. 它是唯一一个在java虚拟机规…

axios如何利用promise无痛刷新token

目录 需求 需求解析 实现思路 方法一&#xff1a; 方法二&#xff1a; 两种方法对比 实现 封装axios基本骨架 instance.interceptors.response.use拦截实现 问题和优化 如何防止多次刷新token 同时发起两个或以上的请求时&#xff0c;其他接口如何重试 最后完整代…

EXCEL教程:如何打开Excel隐藏部分?

在Excel文件中&#xff0c;数据表格的制作是日常工作中不可或缺的一部分。然而&#xff0c;有时候&#xff0c;我们可能会遇到一些数据不方便直接显示但又不能删除的情况。这时&#xff0c;隐藏数据就成为了一个常见的解决方案。但隐藏之后&#xff0c;如何再次打开隐藏部分&am…

socket编程短平快

创建文件描述符 #include<sys/socket.h> int socket_fd socket(AF_INET,SOCK_STREAM,0); //AF_INET address family internet 地址族&#xff0c; 代表ipv4 //SOCK_STREAM TCP协议 //最后的参数是默认配置。文件描述符配置 int opt 1; setsockopt(socket_fd,SOL_SOCK…

SpringBoot 配置文件

目录 一. 配置文件相关概念 二. 配置文件快速上手 1. 配置文件的格式 2. properties 配置文件 (1) properties 基本语法 (2) 读取配置文件内容 (3) properties 缺点分析 3. yml配置文件 (1) yml 基本语法 (2) 读取配置文件内容 (3) yml 配置对象 (4) yml 配置集合 …