动态规划

动态规划是一种非常精妙的算法思想,它没有固定的写法,极其灵活,常常需要具体问题具体分析。(整理自《算法笔记》)

  1. 什么是动态规划:动态规划是一种用来解决一类最优问题的算法思想。简单来说,动态规划是将一个复杂的问题分解成若干个子问题,通过综合子问题的最优解来得到原问题的最优解。需要注意的是,动态规划会将每个求解过的子问题的解记录下来,这样当下一次碰到同样的子问题时,就可以直接使用之前记录的结果,而不是重复计算。
  2. 一般使用递归或者递推的写法来实现动态规划,其中递归写法在此处又称为记忆化搜索。
  3. 动态规划的递归写法:

以斐波那契数列为例。

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

实际上,这个递归涉及了许多重复的计算。为了避免重复计算,可以开一个一维数组 dp。其中dp[n]记录F(n)的结果,并用dp[n]=-1表示F(n)没有被计算过。

int F(int n){
        if( n == 0 || n == 1 )  return 1;//递归边界
        if(dp[n] != -1) return dp[n];//已经计算过,直接返回结果,不再重复计算
        else {
        	dp[n] = F( n-1 ) + F( n-2 )//计算F(n),并保存至dp[n]
        	return dp[n];  //返回F(n)的结果
        }
}

通过记忆化搜索,降低了复杂度。
通过上述例子可以引申一个概念:如果一个问题可以被分解为若干个子问题,且这些子问题会重复出现,那么就称这个问题拥有重叠子问题。一个问题必须拥有重叠子问题,才能使用动态规划去解决。

  1. 动态规划的递推写法
    典型的数塔问题为例(如图):最后将路径上所有数字相加后得到的和最大是多少?在这里插入图片描述

    令dp[i][j]表示从第i行和第j个数字出发的到达最底层的所有路径中能得到的最大和。

如 dp[1][1]就是从位置(1,1)到达最底层的最大和。

用式子表示:dp[i][j] = max (dp[i+1][j],dp[i+1][j+1])+f[1][1]
把dp[i][j]称为问题的状态,而把上面的式子称为状态转移方程。数塔的最后一层的dp值总是等于元素本身,即dp[n][j]==f(n)(j) (1<=j<=n),这种可以直接确定其结果的部分称为边界。这样就可以从最底层各位置的dp值开始,不断往上求出每一层各位置的dp值,最后就会得到dp[1][1]。

根据这种思想写出动态规划的代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn =1000;
int f[maxn][maxn],dp[maxn][maxn];
int main()
{
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
                for(int j=1;j<=i;j++)
                {
                        scanf("%d",&f[i][j]);
                }
        }
        for(int j=1;j<=n;j++)
        {
                dp[n][j]=f[n][j];
        }
        for(int i=n-1;i>=1;i--)
        {
                for(int j=1;j<=i;j++)
                {
                        dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
                }
        }
        printf("%d\n",dp[1][1]);
        return 0;

}


  1. 递推和递归的区别:使用递推写法的计算方式是自底向上,即从边界开始,不断向上解决问题。而使用递归是自顶向下,即从目标问题开始,将他分解为子问题的组合,直至分解为边界为止。
  2. 最优子结构:一个问题的最优解可以由其子问题的最优解有效的构造出来。需要指出,一个问题必须拥有最优子结构,才能使用动态规划去解决。
  3. 分治与动态规划:分治和动态规划都是将问题分解为子问题,然后合并子问题的解得到原问题的解。但分治法分解出的子问题是不重叠的。分治法解决的问题不一定是最优化问题,而动态规划解决的问题一定是最优化问题。
  4. 贪心与动态规划:贪心和动态规划都要求原问题必须拥有最优子结构。如上例的数塔,贪心法就是从最上层开始,每次选择左下和右下两个数字中较大的一个,一直到最底层得到最后结果,显然不一定得到最优解。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方,为未来的学术或职业生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值