第三专题总结(动态规划)

1.定义

动态规划是解决多阶段决策问题的一种方法,也是一种排除重复计算的算法,更具体的说,动态规划就是用空间换取时间。

2.动态规划问题具有以下基本特征: 
(1)问题具有多阶段决策的特征。
(2)每一阶段都有相应的“状态”与之对应,描述状态的量称为“状态变量”。
(3)每一阶段都面临一个决策,选择不同的决策将会导致下一阶段不同的状态。
(4)每一阶段的最优解问题可以递归地归结为下一阶段各个可能状态的最优解问题,各子问题与原问题具有完全相同的结构。

3.动态规划的几个概念

阶段:据空间顺序或时间顺序对问题的求解划分阶段。
状态:描述事物的性质,不同事物有不同的性质,因而用不同的状态来刻画。对问题的求解状态的描述是分阶段的。
决策:根据题意要求,对每个阶段所做出的某种选择性操作。
状态转移方程:用数学公式描述与阶段相关的状态间的演变规律。

4.指导思想

在做每一步决策时,列出各种可能的局部解,依据某种判定条件,舍弃那些肯定不能得到最优解的局部解。以每一步都是最优的来保证全局是最优的

5.动态规划问题的一般解题步骤

(1)判断问题是否具有最优子结构性质,若不具备则不能用动态规划。
(2)把问题分成若干个子问题(分阶段)。
(3)建立状态转移方程(递推公式)。
(4)找出边界条件。
(5)将已知边界值带入方程。
(6)递推求解。

注:动态规划的多阶段决策问题

如果一类问题的求解过程可以分为若干个互相联系的阶段,在每一个阶段都需作出决策,并影响到下一个阶段的决策。多阶段决策问题,就是要在可以选择的那些策略中间,选取一个最优策略,使在预定的标准下达到最好的效果.其依靠的是最优性原理:不论初始状态和第一步决策是什么,余下的决策相对于前一次决策所产生的新状态,构成一个最优决策序列。最优决策序列的子序列,一定是局部最优决策子序列。包含有非局部最优的决策子序列,一定不是最优决策序列。

例题:(最长上升子序列问题)一个数的序列bi,当b1 < b2 < ... < bS 的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... <iK <= N。 比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).你的任务,就是对于给定的序列,求出最长上升子序列的长度。

输入数据
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N 个整数,这些整数的取值范围都在0 到10000。
输出要求
最长上升子序列的长度。
输入样例
7
1 7 3 5 9 4 8
输出样例
4

代码:

#include<iostream>

#include<cstring>

#include<cmath>

#include<algorithm>

int b[MAX_N + 10];
int aMaxLen[MAX_N + 10];
int main()
{
    int i, j, N;
    scanf("%d", & N);
    for( i = 1;i <= N;i ++ )
        scanf("%d", & b[i]);
    aMaxLen[1] = 1;

 for( i = 2; i <= N; i ++ ) 
    { //求以第i 个数为终点的最长上升子序列的长度
        int nTmp = 0; //记录第i 个数左边子序列最大长度
        for( j = 1; j < i; j ++ ) 
        { //搜索以第i 个数左边数为终点的最长上升子序列长度
            if( b[i] > b[j] ) 
            {
                if( nTmp < aMaxLen[j] )
                    nTmp = aMaxLen[j];
            }
        }
        aMaxLen[i] = nTmp + 1;
    }

int nMax = -1;
    for( i = 1;i <= N;i ++ )
        if( nMax < aMaxLen[i])
            nMax = aMaxLen[i];
    printf("%d\n", nMax);
    return 0;
}

经典问题(空间换时间)

楼梯问题

描述:(1)(NUAA 1350)某学校跳楼塔从底到顶只有一个楼梯,共 n 阶,一同学在第 k 次收到 CET-4  <= 250 的证书后欲爬上该塔自行了断,已知该同学每次可以上 1 阶或 2 阶,则他从塔底走到塔顶共有多少种方法?(2)当他爬到塔顶早已累得没有跳下去的勇气了,只想早点回到宿舍去上校内,此时他回城心切,可以每次下 1 阶、 2 阶或 3 阶,则他从塔顶走到塔底共有多少种方法?
输入:只有一个整数 n (1 <= n <= 30)
输出:只有 1 行,包含 2 个整数,中间用空格分开,分别为走上和走下 n 阶楼梯所对应的方法总数
样例输入:3
样例输出:3 4

问题分析
(1)上楼梯时
状态设计:f(i) 表示上 i 阶楼梯所对应的方法总数
求解目标:f(N)
状态转移方程:
f(i) = f(i-1) + f(i-2)        2 <= i <= N
f(i) = 1                            0 <= i <= 1
(2)下楼梯时
状态设计:g(i) 表示下 i 阶楼梯所对应的方法总数
求解目标:g(N)
状态转移方程:
g(i) = g(i-1) + g(i-2) + g(i-3)       3 <= i <= N
g(i) = 2         i = 2
g(i) = 1         i = 1 或 i = 0

代码实现
初始化:

int n, i, f[31], g[31];
scanf("%d", &n);

(1)上楼梯时

f[1] = f[0] = 1;
for (i = 2; i <= n; ++i)
    f[i] = f[i - 1] + f[i - 2];

(2)下楼梯时

g[1] = g[0] = 1;
g[2] = 2;
for (i = 3; i <= n; ++i)
    g[i] = g[i - 1] + g[i - 2] + g[i - 3];




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值