『动态规划』动态规划概述

👨‍🎓作者简介:一位喜欢写作,计科专业大二菜鸟

🏡个人主页:starry陆离

🕒首发日期:2022年8月18日星期四
📚订阅专栏:『算法分析与设计』
🍁每日推荐:牛客网-面试神器
在这里插入图片描述
如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦

@TOC


1.动态规划创始人

动态规划(Dynamic Programming, DP)由 R.Bellman(理查·贝尔曼)教授于1957年提出

Richard Ernest Bellman (1920-1984),美国数学家,美 国艺术与科学院院士,美国工 程院院士,动态规划的创始人。

2.定义

动态规划是将多阶段决策问题进行公式化的一种技术,它是运筹学的一个分支, 用于求解多阶段决策过程的最优化问题

动态规划方程又称为贝尔曼方程

3.总体思想

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子 问题

经分解得到的子问题往往不是互相独立的,有些子问题被重复计算多次

如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就 可以避免大量重复计算,从而得到多项式时间算法

image-20220702224709115

比如这个之前的4.『递归』整数划分问题就计算了很多的重复子问题,我们可以使用动态规划的方法将子问题的解保存起来,避免计算重复的子问题

image-20220702225246461

4.基本要素

最优子结构

一个问题的最优解包含着其子问题的最优解,这种性质称为最优子结构性质

分析问题的最优子结构性质:首先假设由问题的最优解导出的子问题的解不是 最优的,然后再设法说明在这个假设下可构造出比原问题最优解更好的解,从 而导致矛盾

利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步 构造出整个问题的最优解

最优子结构是一个问题能用动态规划算法求解的前提

重叠子问题

递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复 计算多次,这种性质称为子问题的重叠性质

动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当 再次需要解此子问题时,只是简单地用常数时间查看一下结果

5.备忘录法(记忆化搜索)

备忘录方法的控制结构与直接递归方法的控制结构相同

区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避 免相同子问题的重复求解

int solve()
{
    if(备忘录中包含子问题的解) return 备忘录中的值
    else 递归求解
}
int num[n][n];
int q(int n, int m) {
    if((n<1)||(m<1)) return 0;
    if((n==1)||(m==1)) return 1;
    if(n<m) return q(n,n);
    if(n==m) {
        if (num[n-1][n-2]==0) {
            num[n-1][n-2] = q(n,n-1);
        }
        return 1 + num[n-1][n-2];
    }
    if (n>m) {
        if (num[n-1][m-2]==0) {
            num[n-1][m-2] = q(n,m-1);
        }
        if (num[n-m-1][m-1]==0) {
            num[n-m-1][m-1]=q(n-m,m);
        }
        return num[n-1,m-2] + num[n-m-1][m-1];
    }
}

6.斐波那契数列(备忘录法)

如何设计一个去除重复的求斐波那契数列第n项的算法?

7.数字三角形

经典递归解法

int a[110][110],n;
int solve(int i,int j)
{
    if(i==n+1) return 0;
    return a[i][j]+max(solve(i+1,j),solve(i+1,j+1));
}
……
printf("%d\n",solve(1,1)); //(1,1)到最后一层的最大路径和

记忆化搜索(备忘录法)

int p[105][105],a[105][105],n;
int solve(int i,int j)
{
    if(p[i][j]>=0) return p[i][j]; //引入备忘录保存子问题的解
    if(i==n+1) return 0;
    return p[i][j]=a[i][j]+max(solve(i+1,j),solve(i+1,j+1));
}
……
memset(p,-1,sizeof(p)); //初始化备忘录
solve(1,1);
printf(“%d\n”,p[1][1]); //p[1][1]即为所求解

动态规划法(T(n)=O(n^2^))

思路一自底向上求解:p[i][j]表示(i, j)的达到最后一层的最大路径和,那么p[i][j]的最优解 包含了子问题p[i+1][j]p[i+1][j+1]的最优解

状态转移方程如下:这种思路下最终的答案在p[1][1]

image-20220702231148275

image-20220702231245514

int p[105][105],a[105][105],n;
int solve()
{
    for(int j=1;j<=n;j++) p[n][j]=a[n][j];
    for(int i=n-1;i>=1;i--) //自底向上DP
        for(int j=1;j<=i;j++)//对行遍历
            p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1]);
}
……
solve();
printf("%d\n",p[1][1]);

思路二自顶向下:p[i][j]表示从(1,1)到达(i, j) 的最大路径和,那么p[i][j]的最优解包 含了子问题p[i-1][j-1]p[i-1][j]的最优解

状态转移方程如下:这种思路下最终的答案在p[n][j]

image-20220702231505391

image-20220702231638875

🍁每日推荐:牛客网-面试神器
在这里插入图片描述

#动态规划#
全部评论
我每次动态规划的都看不懂
1 回复 分享
发布于 2022-08-19 09:15 陕西

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
评论
2
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务