动态规划

动态规划是一种将大问题拆解成子问题并利用子问题的解来解决原问题的算法。它通常涉及状态定义、状态转移方程、初始化状态和返回结果。本文通过斐波那契数列、变态青蛙跳台阶、矩形覆盖、最大连续子数组和、字符串分割以及三角矩阵等实例,详细阐述了动态规划的适用场景和解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划的基本思想

动态规划是分治思想的延伸,通俗一点就是大事化小,小事化无的艺术。在将大问题化解为小问题的分治过程中,保存对这些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果。

动态规划的特点

动态规划具备以下三个特点:
1把原来的问题分解成了几个相似的子问题
2所有的子问题都只需要解决一次
3储存子问题的解

动态规划的本质

动态规划的本质,是对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)
动态规划问题一般从以下四个角度考虑
1状态定义
2状态间的转移方程定义
3状态初始化,确定的值,不以输入的变化而变化,或者是空状态(尽量有意义)
4返回结果

状态定义的要求:定义的状态一定要形成递推关系。
三特点四要素两本质

适用场景

最大值/最小值、可不可行、是不是、方案个数

例一:斐波那契数列

int Fib(int n)
{
	if(n<=0)
		return 0;
	if(n==1 || n==2)
		return 1;
	return Fib(n-1)+Fib(n-2);
}

n>2时,O(2n)栈溢出,重复计算
状态:F(i)数列dii项的值
递推:F(i)=F(i-1)+F(i-2)
状态初始化:F(1) = F(2) = 1 F(0) = 0
返回结果:F(n)

//动态规划
#include<vector>
int FibDp(int n)
{
	if(n<=0)
		return 0;
	vector<int> fab(n+1,0);
	//初始化
	fab[0] = 0;
	fab[1] = 1;
	//状态递推
	for(int i = 2; i<=n; i++)
	{
		//F(i) = F(i-1)+F(i-2)
		fab[i] = fab[i-1]+fab[i-2];
	}
	//返回结果F(n)
	return fab[n];
}

上述代码的空间复杂度为O(n),可以优化为O(1)利用三个临时变量来代替数组

例二 变态青蛙跳台阶

状态:F(i),青蛙跳上台阶的方法数
递推:
跳上1阶,2阶,…n阶
跳1阶,还剩n-1 ----> F(n-1)
跳2阶,还剩n-2 ----> F

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值