前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【算法】动态规划算法

【算法】动态规划算法

作者头像
半生瓜的blog
发布2023-05-13 13:36:38
1890
发布2023-05-13 13:36:38
举报
文章被收录于专栏:半生瓜のblog

动态规划算法

走楼梯,可以一次上一阶,也可以,一次上两阶,根据楼梯的阶数来判断有几种上楼梯的方法。

分析

f(1) = 1; 1种 f(2) = 2; 2种 f(3) = f(1) + f(2);3种 f(4) = f(3) + f(2) ;5种 … 依次类推

代码如下:

代码语言:javascript
复制
#include<iostream>
using namespace std;

int WalkCount(int n)
{
	//可以一次走一阶台阶,也可以一次走两阶台阶
	if (n < 0)
	{
		return  0;
	}
	if (n == 1)
	{
		return 1;
	}
	if (n == 2)
	{
		return 2;
	}
	else {
		return WalkCount(n-1)+WalkCount(n-2);
	}
}
int main(void)
{
	cout << WalkCount(45) << endl;
	return 0;
}

我们发现,当楼梯结束过大的时,会因为内存消耗过大而发生栈溢出。

因为调用了大量重复的函数,将栈消耗光了。


解决办法:避免重复计算的部分,将重复计算的值保存下来。

代码语言:javascript
复制
long long  WalkCount(int n)
{

	long long  ret = 0;
	if (n <= 0)
	{
		return 0;
	}
	if (n == 1)
	{
		return 1;
	}
	if (n == 2)
	{
		return 2;
	}
	long long * value = new long long[n + 1];//索引从0开始
	value[0] = 0;
	value[1] = 1;
	value[2] = 2;

	for (int i = 3; i <= n; i++)
	{
		value[i] = value[i - 1] + value[i - 2];
	}

	ret = value[n];
	delete value;
	return ret;
}

动态规划算法也是一种分治的思想

分治算法是把原问题分解为若干子问题,自顶向下,求解子问题,合并子问题的解从而得到原问题的解。 动态规划也是自顶向下把原问题分解为若干子问题,不同的是然后,自底向上,先求解最小的子问题,把结果存储在表格中,在求解大的子问题时,直接从表格中查询小的子问题的解 ,避免重复计算,从而提高了算法效率。 (就是定义了一个数组存储之前得到的内容,累加到传进来的对应值。)

什么时候使用动态规划算法

如果要求一个问题的最优解(通常是最大值或者最小值),而且该问题能能够分解为若干子问题,并且小问题之间也存在 重叠的子问题,则考虑使用动态规划。

怎么使用动态规划

五部曲

  1. 判断题意是否找出一个问题的最优解。
  2. 从上往下分析问题,大问题可以分解为子问题,子问题中还有更小的问题。
  3. 从下网上分析问题,找出这些问题之间的关联(状态转移方程)。
  4. 讨论底层的边界问题。
  5. 解决问题(通常使用数组进行迭代求出最优解)

练习

给定一根线段,长为n,分成m段,最大的乘积是多少? 例如:长为10,最大分为3*4 *2 = 36 感谢这位老哥分享思路剑指offer–剪绳子(动态规划+贪心算法)详解

代码语言:javascript
复制
//传进来的是绳子的长度
int CutRope(int n)
{
	int result = 0;
	if (n <= 1)
	{
		return 0;
	}
	if (n == 2)
	{
		return 2;
	}
	if (n == 3)
	{
		return 3;
	}
	//动态开辟数组
	int* temp = new int[n + 1];//数组索引从0开始
	//绳子多长(n多大),对应分割的最大乘积就存在数组对应下标所指向的值temp[n]
	temp[0] = 0;
	temp[1] = 0;
	temp[2] = 2;
	temp[3] = 3;
	/*
	我们不需要去考虑到底要分割成多少段求出来的乘积才是最大的,
	每次分割成都两段,这两段的乘积最大值已经在之前求出来并且存到了temp中对应的位置上了,
	我们只需要对比这几种分割(分成两段的不同情况,这两段最大的乘积都是多少)选出最大的,
	放到该长度n,在temp数组中的位置即可。
	例: 4 可以分为1 3,2 2 ,3 1 
	1、2、3分成的乘积最大值,在之前已经求出来了,最需要分成这两种的乘积即可。
	3 4 3 最大为 4 ,存进temp[4] = 4;
	
	*/
	for (int i = 4; i <= 4; i++)
	{
		int max = 0;//保存当前长度乘积最大的。
		//循环计算出最大的
		for (int j = 1; j <= i / 2; j++)
		{
			if (max < temp[j] * temp[i - j])
			{
				max = temp[j] * temp[i - j];
			}
		}
		temp[n] = max;
	}
	result = temp[n];
	delete temp;
	return  result;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态规划算法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档