2026-01-09 14:24:10
动态规划是一种解决复杂问题的方法,通过将问题分解为更小的子问题,并存储子问题的解以避免重复计算,从而高效地找到原问题的解。以下是我对动态规划的个人总结,结合实习招聘中常见的编程题以及背包问题、最长公共子序列/串等经典例子进行阐述。
一、动态规划的应用场景在编程题中,当遇到看似复杂、难以直接求解的问题时,动态规划往往是一个有效的解决方案。特别是当问题具有重叠子问题和最优子结构特性时,动态规划能够显著减少计算量,提高解题效率。
二、动态规划的基本概念背包问题是动态规划中的经典问题,包括01背包、完全背包和多重背包等类型。
01背包:每件物品只能拿一次。使用二维数组dp[i][j]表示面对第i件物品,其背包容量剩下j时,能获得的最大价值。状态转移方程为:
dp[i][j] = dp[i-1][j](当j < c[i]时,拿不了这件物品)
dp[i][j] = max{dp[i-1][j], dp[i-1][j-c[i]]+w[i]}(当j >= c[i]时,比较拿和不拿的两种价值)
完全背包:每件物品可以无限次使用。与01背包的不同在于,第二层循环时j的取值从c[i]到V,状态转移方程与01背包类似,但循环顺序不同。
多重背包:第i件物品有对应的数量。可以转化为01背包问题,添加一层循环来设置物品的数量,状态转移方程为:dp[i][j] = max{dp[i-1][j], dp[i-1][j-k*c[i]]+k*w[i]}。
示例图片:

最长公共子序列:使用二维数组dp[i][j]表示遍历到序列A的第i个字符和序列B的第j个字符的公共序列的最长长度。状态转移方程为:
dp[i][j] = dp[i-1][j-1] + 1(当A[i-1] == B[j-1]时)
dp[i][j] = max{dp[i-1][j], dp[i][j-1]}(当A[i-1] != B[j-1]时)
最长公共子串:与最长公共子序列不同的是,最长公共子串需要连续的子串。当对应元素不同的时候,dp[i][j] = 0。同时还需要一个整数来记录长度,用于比较历史结果和当前的dp长度,更新最大值。
示例图片:

最长回文字串问题也是动态规划的一个经典应用。可以使用二维数组dp[i][j]表示字符串从i到j的子串是否为回文串。状态转移方程为:
在遍历过程中,记录最长的回文字串长度和起始位置。
四、动态规划的解题步骤动态规划是一种强大的算法设计技术,适用于解决具有重叠子问题和最优子结构特性的问题。通过定义状态、推导状态转移方程、初始化、计算顺序和结果输出等步骤,可以有效地求解复杂问题。在实习招聘中,掌握动态规划的思想和方法,对于提高编程能力和解题效率具有重要意义。