动态规划算法

简介:
斐波纳契数列F(n)

n

0

1

2

3

4

5

6

7

8

9

10

F(n)

1

1

2

3

5

8

13

21

34

55

89

递归 vs 动态规划

递归版本(太慢):

int f(int n)
{
    if(n <= 1) return 1;
    else return f(n-1)+f(n-2);
}

动态规划版本(有效率!算法复杂度是 O(n)):

int a[1000];
int f(int n)
{
    a[0]=a[1]=1;
    for(int i=2; i<=n; i++)
        a[i]=a[i-1]+a[i-2];
    return a[n];
}

方法概要

构造一个公式,它表示一个问题的解是与它的子问题的 解相关的公式.   E.g.  F(n) = F(n-1) + F(n-2).

为这些子问题做索引 ,以便它们能够在表中更好的存储与检索 (i.e., 数组array[])

以自底向上的方法来填写这表格; 首先填写最小子问题的解.

这就保证了当我们解决一个特殊的子问题时, 可以利用比它更小的所有可利用的 子问题的解.

动态规划算法原理

算法思想:

将待求解的问题分解成若干个子问题,并存储子问题的解而避免计算重复的子问题,并由子问题的解得到原问题的解。

动态规划算法通常用于求解具有某种最优性质的问题。

动态规划算法的基本要素:最优子结构性质和重叠子问题。

原理:

最优子结构性质:问题的最优解包含着它的子问题的最优解。即不管前面的策略如何,此后的决策必须是基于当前状态(由上一次决策产生)的最优决策。

重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些问题被反复计算多次。对每个子问题只解一次,然后将其解保存起来,以后再遇到同样的问题时就可以直接引用,不必重新求解。

解决问题的基本特征:

1. 动态规划一般解决最值(最优,最大,最小,最长……)问题;

2. 动态规划解决的问题一般是离散的,可以分解(划分阶段)的;

3. 动态规划解决的问题必须包含最优子结构,即可以由(n-1)的最优推导出n的最优

解决问题的基本步骤:

动态规划算法的4个步骤:

1. 刻画最优解的结构特性. (一维,二维,三维数组)

2. 递归的定义最优解. (状态转移方程)

3. 以自底向上的方法来计算最优解.

4. 从计算得到的解来构造一个最优解.

举例实战

例题一.   斐波纳契数列F(n)

步骤1:用F(n)表示在斐波纳契数列中第n个数的值;

步骤2:状态转移方程:

 

步骤3:以自底向上的方法来计算最优解

n

0

1

2

3

4

5

6

7

8

9

10

F(n)

1

1

2

3

5

8

13

21

34

55

89

步骤4:在数组中分析构造出问题的解;

例题二.   输入n,求出n!

步骤1:用F(n)表示n!的值;

步骤2:状态转移方程:

步骤3:以自底向上的方法来计算最优解

n

0

1

2

3

4

5

6

7

8

9

10

F(n)

1

1

2

6

24

120

720

       

例题三:排队买票问题

一场演唱会即将举行。现有n个歌迷排队买票,一个人买一张,而售票处规定,一个人每次最多只能买两张票。假设第i位歌迷买一张票需要时间 Ti(1≤i≤n),队伍中相邻的两位歌迷(第j个人和第j+1个人)也可以由其中一个人买两张票,而另一位就可以不用排队了,则这两位歌迷买两张票的时 间变为Rj,假如Rj<Tj+Tj+1,这样做就可以缩短后面歌迷等待的时间,加快整个售票的进程。现给出n, Tj和Rj,求使每个人都买到票的最短时间和方法。

分析:

如果前i个人买票的最优买票方式一确定,比如第i-1个人买一张票,则前i-1个人的买票方式也一定是最优的。即问题的最优解包含子问题的最优解。

步骤1:用F(i)表示前i个人买票的最优方式,即所需最短时间;现在要决定F(i)需要考虑两种情况:

(1)第i个人的票自己买

(2)第i个人的票由第i-1个人买

步骤2:状态转移方程:

步骤3:以自底向上的方法来计算最优解

程序的实现(伪代码):

BuyTicks(T, R)
1    n ← length[T] 
2    f[0] ← 0
3    f[1] ← T[1]
4    for i ← 2 to n do 
5                 f[i] ← f[i-2]+R[i-1]
6                 if  f[i] > f[i-1]+T[i] then 
7                     f[i] ← f[i-1]+T[i]
8    return f
目录
相关文章
|
5月前
|
机器学习/深度学习 存储 算法
动态规划算法深度解析:0-1背包问题
0-1背包问题是经典的组合优化问题,目标是在给定物品重量和价值及背包容量限制下,选取物品使得总价值最大化且每个物品仅能被选一次。该问题通常采用动态规划方法解决,通过构建二维状态表dp[i][j]记录前i个物品在容量j时的最大价值,利用状态转移方程避免重复计算子问题,从而高效求解最优解。
677 1
|
存储 算法
深入了解动态规划算法
深入了解动态规划算法
461 1
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
238 8
|
12月前
|
存储 算法 Java
算法系列之动态规划
动态规划(Dynamic Programming,简称DP)是一种用于解决复杂问题的算法设计技术。它通过将问题分解为更小的子问题,并存储这些子问题的解来避免重复计算,从而提高算法的效率。
466 4
算法系列之动态规划
|
算法 Java C++
【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题
本文介绍了经典的0/1背包问题及其动态规划解法。
467 5
|
算法 安全 调度
【动态规划篇】穿越算法迷雾:约瑟夫环问题的奇幻密码
【动态规划篇】穿越算法迷雾:约瑟夫环问题的奇幻密码
|
机器学习/深度学习 算法 测试技术
【动态规划篇】01 背包的逆袭:如何用算法装满你的 “财富背包”
【动态规划篇】01 背包的逆袭:如何用算法装满你的 “财富背包”
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
756 2
动态规划算法学习三:0-1背包问题
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
310 2

热门文章

最新文章