「程序员必须掌握的算法」动态规划「上篇」

这篇具有很好参考价值的文章主要介绍了「程序员必须掌握的算法」动态规划「上篇」。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

动态规划详解

动态规划 (Dynamic Programming) 是一种算法思想,用于解决一些复杂的问题。本文将介绍动态规划的分类、概念和经典例题讲解。

动态规划的分类

动态规划可以分为以下两种类型:

  1. 0/1背包问题:该问题是动态规划的一种基本类型。在背包问题中,有n个物品可以放入容量为W的背包中,每个物品有自己的重量和价值。需要选择哪些物品能够最大化背包的总价值。
  2. 最长公共子序列问题:该问题是另一种经典的动态规划类型,涉及到两个字符串,并找到这两个字符串之间的最长公共子序列。

动态规划的概念

在解决动态规划问题时,我们需要定义以下概念:

  1. 状态 (State):问题中需要优化的变量,如背包问题中的容量,最长公共子序列问题中的字符串长度等。
  2. 状态转移方程 (State Transition Equation):描述状态之间的转移过程,即问题的递推关系。例如,在背包问题中,每个物品可以放入背包或不放入背包。因此,状态转移方程可以表示为: d p [ i ] [ j ] = max ⁡ ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w i ] + v i ) dp[i][j] = \max(dp[i-1][j], dp[i-1][j-w_i]+v_i) dp[i][j]=max(dp[i1][j],dp[i1][jwi]+vi) 其中dp[i][j]表示在使用前i个物品时,填满j容量的背包的最大价值。
  3. 初始状态 (Initial State):问题的初始条件,通常为问题规模最小的情况下的答案。在背包问题中,初始状态为dp[0][0]=0。
  4. 边界状态 (Boundary State):问题的边界条件,在状态转移过程中需要特别处理的状态。在背包问题中,背包的容量不能为负数,因此需要在状态转移方程中特别处理。

经典例题讲解

下面我们将分别介绍0/1背包问题和最长公共子序列问题的解法。

1. 0/1背包问题

题目描述:有n个物品和一个容量为W的背包。第i个物品的重量为wi,价值为vi。现在,需要选择一些物品放入背包,使得放入的物品的总重量不超过W,且总价值最大。求最大价值。

解题思路:定义状态dp[i][j]为在使用前i个物品时,填满j容量的背包的最大价值。状态转移方程如下所示: d p [ i ] [ j ] = { d p [ i − 1 ] [ j ] , j < w i max ⁡ ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w i ] + v i ) , j ≥ w i dp[i][j] = \begin{cases}dp[i-1][j],&j<w_i\\ \max(dp[i-1][j], dp[i-1][j-w_i]+v_i),&j\ge w_i\end{cases} dp[i][j]={dp[i1][j],max(dp[i1][j],dp[i1][jwi]+vi),j<wijwi 其中dp[i-1][j]表示不放入第i个物品的最大价值,dp[i-1][j-w[i]]+v[i]表示将第i个物品加入背包的最大价值。需要注意的是,如果当前背包容量小于物品的重量,就不能将该物品放入背包。因此,需要特别处理背包容量小于物品重量的情况。

代码实现:

int dp[101][1001];
int weight[101], value[101];

int knapSack(int n, int w)
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= w; j++) {
            if (j < weight[i]) {
                dp[i][j] = dp[i-1][j];
            } else {
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);
            }
        }
    }
    return dp[n][w];
}

2. 最长公共子序列问题

题目描述:给定两个字符串A和B,找到它们的最长公共子序列 (LCS)。

解题思路:定义状态dp[i][j]为字符串A的前i个字符和字符串B的前j个字符的LCS长度。状态转移方程如下所示:

d p [ i ] [ j ] = { 0 , i = 0 或 j = 0 d p [ i − 1 ] [ j − 1 ] + 1 , A i = B j max ⁡ ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) , A i ≠ B j dp[i][j] = \begin{cases}0,&i=0\text{或}j=0\\ dp[i-1][j-1]+1,&A_i=B_j\\ \max(dp[i-1][j], dp[i][j-1]),&A_i\neq B_j\end{cases} dp[i][j]= 0,dp[i1][j1]+1,max(dp[i1][j],dp[i][j1]),i=0j=0Ai=BjAi=Bj

当A[i-1]等于B[j-1]时,dp[i][j]等于dp[i-1][j-1]+1,表示A和B中的相同字符加上它们前面的LCS。当它们不相等时,LCS为它们前面的LCS的最大值,即dp[i-1][j]和dp[i][j-1]的最大值。

代码实现:

int dp[1001][1001];
string A, B;

int LCS(int n, int m)
{
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            if (i == 0 || j == 0) {
                dp[i][j] = 0;
            } else if (A[i-1] == B[j-1]) {
                dp[i][j] = dp[i-1][j-1] + 1;
            } else {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }
    return dp[n][m];
}

结语

动态规划是一种非常重要的算法思想,它通常用于解决复杂的问题。在应用动态规划解决问题时,需要注意定义状态、状态转移方程、初始状态和边界状态等概念。对于不同类型的动态规划问题,需要采用不同的解决方法。希望本文能够帮助读者加深对动态规划的理解。文章来源地址https://www.toymoban.com/news/detail-733647.html

到了这里,关于「程序员必须掌握的算法」动态规划「上篇」的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 程序员必须掌握哪些算法?——前端开发工程师需要掌握的算法

    一个程序员一生中可能会邂逅各种各样的算法,但总有那么几种,是作为一个程序员一定会遇见且大概率需要掌握的算法。作为一名前端开发工程师,今天就通过这个话题和文章来聊聊前端开发工程师需要掌握的算法有哪些呢。 算法(Algorithm) 是指解题方案的准确而完整的

    2024年02月15日
    浏览(73)
  • 「必学算法」- 作为一个程序员,你一生中必须掌握的几种算法

    作为一个程序员,学习算法是不可避免的一个过程。算法不仅可以提高编程能力,也可以让我们更好地应对各种实际问题。在实际编程过程中,我们经常会用到一些常见的算法,这些算法具有广泛的应用,掌握它们对提升编程能力和解决实际问题非常有帮助。 下面列举了一些

    2024年02月17日
    浏览(63)
  • 9个程序员必须掌握的Git命令

    介绍一些非常实用的Git命令。 微信搜索关注《Java学研大本营》 Git是最常用的版本控制系统之一。然而,对于初学者来说,Git的众多命令和工作流程会让人感到困惑和棘手。在Git的世界中很容易迷失,遇到合并冲突错误和意外更改,Git对于新手来说可能真的是一场噩梦。 本文

    2024年01月21日
    浏览(62)
  • Kali中搭建vulhub时镜像git失败_vulhub git,每个程序员都必须掌握的8种数据结构

    先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新网络安全全套学习资料》

    2024年04月27日
    浏览(56)
  • 学PYTHON必须学算法吗?老程序员告诉你真相!

    通过以上所学内容大家就可以比较清楚的了解到Python编程学完可以做什么了,主要可以选择的工作我挑了以下几个介绍: (1) 大数据分析师 :基于各种分析手段对大数据进行科学分析、挖掘、展现并用于决策支持。使企业清晰的了解到现状及竞争环境。 (2) 人工智能 :

    2024年02月06日
    浏览(61)
  • 作为一个程序员一定要掌握的算法之遗传算法

    目录 一、引言 1.1 目的 1.2 意义 二、遗传算法介绍 2.1 遗传算法的基本思想 2.2 遗传算法与其他算法的主要区别 2.3 基于Java的遗传算法设计思想 三、遗传算法的具体实现 3.1 系统功能模块图和说明 3.2 代码和说明 3.2.1 初始化 3.2.2 选择运算 3.2.3 交叉运算 3.2.4 变异运算 3.2.5 主函

    2024年02月15日
    浏览(61)
  • 探索编程世界的宝藏:程序员必掌握的20大算法

    #程序员必须掌握哪些算法?# 在当今数字化时代,程序员们仍然需要拥有一把解决问题和优化代码的金钥匙。这些钥匙是算法,它们隐藏在计算机科学的宝藏中,等待着我们去发现和掌握。本篇博文将带你踏上一段引人入胜的探险之旅,揭开程序员必须掌握的20大算法的神秘

    2024年02月14日
    浏览(231)
  • 有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”

    作为IT程序员,学习算法的原因主要有以下几点: 提升问题解决能力:算法可以帮助程序员分析、优化和解决复杂问题。了解算法原理和实现方式将有助于程序员更快地找到合适的解决方案。这对于解决实际工作中的问题是非常有帮助的。 提高代码效率:通过学习不同的算法

    2024年02月13日
    浏览(36)
  • 《程序员面试金典(第6版)》 面试题 08.11. 硬币(动态规划,组合问题,C++)

    硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007) 示例1: 输入: n = 5 输出:2 解释: 有两种方式可以凑成总金额: 5=5 5=1+1+1+1+1 示例2: 输入: n = 10 输出:4 解释: 有四种方式可以凑成总金额: 1

    2023年04月08日
    浏览(55)
  • 程序员必须了解的 10个免费 Devops 工具

    近年来,DevOps 已经成为一门将软件开发 (Dev) 与 IT 运维 (Ops) 相融合的重要学科,目的是为了缩短软件的开发生命周期并提供高质量软件的持续交付。 这篇文章整理了十种基本的免费开源的 DevOps 工具,这些工具已经在实践中得到了证明,凭借有效性和能够简化 DevOps 流程的能

    2024年04月11日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包