【基础算法】动态规划

举报
幼儿园老大* 发表于 2024/10/29 21:33:49 2024/10/29
【摘要】 一、动态规划的定义动态规划(Dynamic Programming,DP)是一种用于解决优化问题的算法策略。它通过将一个复杂的问题分解为一系列相互关联的子问题,并利用子问题的解来构建原问题的解。其核心思想是避免重复计算,通过记录已经解决的子问题的解(通常使用表格或数组来存储),在需要时直接查找这些解,从而提高计算效率。二、动态规划的基本要素状态(State)状态是对问题在某一时刻或某一阶段的...
一、动态规划的定义


动态规划(Dynamic Programming,DP)是一种用于解决优化问题的算法策略。它通过将一个复杂的问题分解为一系列相互关联的子问题,并利用子问题的解来构建原问题的解。其核心思想是避免重复计算,通过记录已经解决的子问题的解(通常使用表格或数组来存储),在需要时直接查找这些解,从而提高计算效率。


二、动态规划的基本要素


  1. 状态(State)
    • 状态是对问题在某一时刻或某一阶段的描述。例如,在计算斐波那契数列时,第 n 个斐波那契数就是一个状态。状态通常用一个变量或一组变量来表示。在背包问题中,背包的剩余容量和已经考虑的物品集合就是状态的一部分。
    • 状态转移方程(State Transition Equation)
      • 它描述了如何从一个或多个已知的状态推导出其他状态。例如,斐波那契数列的状态转移方程为 ,表示第 n 个斐波那契数可以由第  个和第  个斐波那契数相加得到。状态转移方程是动态规划的核心,它体现了子问题之间的关系。
    • 边界条件(Base Case)
      • 边界条件是问题的最简单情况,用于初始化动态规划的过程。在斐波那契数列中, 就是边界条件。没有边界条件,状态转移方程就无法开始计算。
  2. 三、动态规划的解题步骤

    1. 定义状态:明确问题中的状态变量,确定如何用这些变量来描述问题的各个阶段。
    2. 确定状态转移方程:根据问题的逻辑,找出状态之间的递推关系,即如何从已知状态推导出新的状态。
    3. 确定边界条件:找出问题的最简单情况,为动态规划的计算提供初始值。
    4. 计算顺序和存储结果:根据状态转移方程,确定计算状态的顺序,通常是按照状态变量的递增或递减顺序进行计算。同时,需要一个数据结构(如数组或表格)来存储计算得到的状态值,以便在后续计算中重复利用。
      四、动态规划的应用场景

      1. 斐波那契数列(优化版)
        • 原始的递归计算斐波那契数列会存在大量重复计算。使用动态规划可以避免这种情况。
        • 代码实现(以 Java 为例):
        • public class FibonacciDP {
              public static int fibonacci(int n) {
                  if (n == 0 || n == 1) {
                      return n;
                  }
                  int[] dp = new int[n + 1];
                  dp[0] = 0;
                  dp[1] = 1;
                  for (int i = 2; i <= n; i++) {
                      dp[i] = dp[i - 1] + dp[i - 2];
                  }
                  return dp[n];
              }
          }
          1. 背包问题
            • 0 - 1 背包问题描述:有一个容量为  的背包和  个物品,每个物品有重量  和价值 。每个物品要么放入背包,要么不放入背包,要求在不超过背包容量的情况下,选择物品使得背包内物品的总价值最大。
            • 代码实现(以 Java 为例):
            • public class Knapsack {
                  public static int knapsack(int C, int[] w, int[] v, int n) {
                      int[][] dp = new int[n + 1][C + 1];
                      for (int i = 1; i <= n; i++) {
                          for (int j = 0; j <= C; j++) {
                              if (w[i - 1] <= j) {
                                  dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
                              } else {
                                  dp[i][j] = dp[i - 1][j];
                              }
                          }
                      }
                      return dp[n][C];
                  }
              }
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。