当前位置: 首页 > news >正文

动态规划经典问题学习笔记

动态规划概述

        动态规划(Dynamic Programming,简称DP)是一种通过将原问题分解为子问题,并存储子问题的解来避免重复计算的优化技术。它通常用于解决具有重叠子问题和最优子结构性质的问题。

动态规划的核心思想

  • 分解问题:将原问题分解为更小的子问题。
  • 存储子问题解:将子问题的解存储在表格(通常是数组或矩阵)中,避免重复计算。
  • 构建最优解:从子问题的最优解构建原问题的最优解。

动态规划的适用条件

  • 重叠子问题:问题的递归解包含重复的子问题。
  • 最优子结构:问题的最优解可以由子问题的最优解有效地构建。

经典问题列表

1. 爬楼梯问题

问题描述

        假设你正在爬楼梯,需要 n 阶才能到达楼顶。每次你可以爬 1 或 2 个台阶,有多少种不同的方法可以爬到楼顶?

解题思路
  • 递推关系:设 f(n) 为爬到第 n 阶的方法数。由于最后一步只能是爬 1 阶或 2 阶,因此 f(n) = f(n-1) + f(n-2)
  • 边界条件:f(1) = 1(1阶只有1种方法),f(2) = 2(2阶有两种方法:1+1 或 2)
完整代码
#include <iostream>
using namespace std;int climbStairs(int n) {if (n <= 2) {return n;}int a = 1, b = 2;for (int i = 3; i <= n; i++) {int c = a + b;a = b;b = c;}return b;
}int main() {int n = 5;cout << "爬" << n << "阶楼梯的方法数:" << climbStairs(n) << endl; // 输出:8return 0;
}

2. 最长公共子序列问题

问题描述

        给定两个字符串 text1 和 text2,返回它们的最长公共子序列的长度。如果不存在公共子序列,返回 0。

        子序列是指在保持相对顺序的情况下,可以通过删除一些字符(也可以不删除)而不改变其余字符顺序的序列。

解题思路
  • 动态规划定义:设 dp[i][j] 表示 text1[0...i-1](前 i 个字符)和 text2[0...j-1](前 j 个字符)的最长公共子序列长度。
  • 递推关系:
    • 若 text1[i-1] == text2[j-1](当前字符相同),则 dp[i][j] = dp[i-1][j-1] + 1
    • 若字符不同,则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])
  • 边界条件:dp[0][j] = 0text1 为空),dp[i][0] = 0text2 为空)
完整代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;int lCS(string text1, string text2) {int m = text1.size();int n = text2.size();vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){if (text1[i - 1] == text2[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[m][n];
}int main(){string text1 = "abcde";cout << "第一个字符串为:" << text1 << endl;string text2 = "ace";cout << "第二个字符串为:" << text2 << endl;cout << "两个字符串的最长公共子序列长度为:" << lCS(text1, text2) << endl;return 0;
}

3. 编辑距离问题

问题描述

        给定两个单词 word1 和 word2,计算将 word1 转换成 word2 所使用的最少操作数。

        允许的操作有:插入一个字符、删除一个字符、替换一个字符。

解题思路
  • 动态规划定义:设 dp[i][j] 表示将 word1[0...i-1](前 i 个字符)转换为 word2[0..j-1](前 j 个字符)的最少操作数。
  • 递推关系:
    • 若 word1[i-1] == word2[j-1](当前字符相同),则无需操作:dp[i][j] = dp[i-1][j-1]
    • 若字符不同,则取以下三种操作的最小值+1:
      • 替换:dp[i-1][j-1] + 1
      • 删除:dp[i-1][j] + 1
      • 插入:dp[i][j-1] + 1
  • 边界条件:
    • dp[0][j] = jword1 为空,需插入 j 个字符)
    • dp[i][0] = iword2 为空,需删除 i 个字符)
完整代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;int minDistance(string word1, string word2) {int m = word1.size();int n = word2.size();vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));// 初始化边界for (int i = 0; i <= m; i++) {dp[i][0] = i;}for (int j = 0; j <= n; j++) {dp[0][j] = j;}// 填充DP表for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (word1[i - 1] == word2[j - 1]) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = min(min(dp[i - 1][j - 1] + 1,  // 替换dp[i - 1][j] + 1),     // 删除dp[i][j - 1] + 1          // 插入);}}}return dp[m][n];
}int main() {string word1 = "horse";cout << word1 << endl;string word2 = "ros";cout << word2 << endl;cout << "最少编辑次数:" << minDistance(word1, word2) << endl;  // 输出:3return 0;
}

4. 0/1背包问题

问题描述

        有 n 件物品和一个容量为 capacity 的背包。第 i 件物品的重量为 weight[i],价值为 value[i]。每件物品只能选择一次(要么放入,要么不放入),求背包能容纳的最大总价值。

解题思路
  • 动态规划定义:设 dp[i][j] 表示前 i 件物品中,选出总重量不超过 j 的物品的最大价值.
  • 递推关系:
    • 若不选第 i 件物品:dp[i][j] = dp[i-1][j]
    • 若选第 i 件物品(需满足 weight[i-1] ≤ j):dp[i][j] = dp[i-1][j - weight[i-1]] + value[i-1]
    • 取两者的最大值:dp[i][j] = max
  • 边界条件:
    • dp[0][j] = 0(前0件物品,价值为0)
    • dp[i][0] = 0(背包容量为0,价值为0)
完整代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int knapsack01(int capacity, vector<int> & weight, vector<int>& value) {int n = weight.size();vector<vector<int> > dp(n + 1, vector<int>(capacity + 1, 0));for (int i = 1; i <= n; i++) {int w = weight[i - 1];int v = value[i - 1];for (int j = 1; j <= capacity; j++) {if (w > j) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - w] + v);}}}return dp[n][capacity];
}int main() {int capacity = 4;vector<int> weight = {2, 1, 3};vector<int> value = {4, 2, 3};cout << "背包最大价值:" << knapsack01(capacity, weight, value) << endl;return 0;
}

http://www.dtcms.com/a/513195.html

相关文章:

  • java重构旧代码有哪些注意的点
  • 湛江廉江网站建设WordPress留言表单仿制
  • 如何优化一个网站案例网站模板_案例网
  • 青岛开发网站深圳福田区房子价格
  • JeecgBoot积木报表综合漏洞检测工具
  • 南召微网站开发免费开发游戏的软件
  • 寻找网站建设 网站外包wordpress评论页面美化
  • 营销网站建设企业筑人才官网
  • 多模态是什么意思
  • 在线音乐网站开发php上海资格证报名网站
  • 企业网站建设协议淘宝上可以做网站吗
  • 【JDBC】实战 养老中心护理项目的增删改查
  • 智慧校园顶层规划设计方案PPT(62页)
  • MATLAB | 函数或变量无法识别 / 函数缺失
  • 做网站用笔记本电脑wordpress 大内存
  • qq刷赞网站怎么做的网页策划案
  • 邯郸做网站多少钱企业网站的建立联系方式
  • 汕头网站建设培训公司免费微信网站制作
  • 新建网站推广给企业海口网站建设哪个好薇
  • jmeter测试dubbo接口
  • AI体测设备哪家好供应商
  • 网上做预算的网站宿州集团网站建设
  • 微信网站怎么做的好处站长统计性宝app
  • 网商网站怎么做合肥建站网站模板
  • 从零开始学阿里云服务器安全管理:防攻击、防泄漏、防漏洞
  • Berachain 推出原生借贷板块 BEND,为 PoL 生态进一步注入资金循环能力
  • 深圳罗湖外贸网站建设怎么做网站网站
  • 4.5.更新数据
  • 网站新闻更新怎么设计wordpress标题调用标签
  • HPjtune.jar 使用教程(附下载与调优步骤)​