一文彻底弄懂动态规划【DP】

news2025/1/28 23:24:56

在这里插入图片描述

动态规划是一种重要的算法,它能解决很多看似复杂的问题,关键在于找到问题的子问题结构,并根据子问题的解决方式来解决原问题。首先要了解的是动态规划的基本思想:

动态规划的基本思想是:将一个复杂的问题分解为一系列相关的子问题,每个子问题只解决一次,并将结果储存在一个可以查找的数据结构中(通常是一个数组或表格)。当要解决相同的子问题时,不需要重新计算,而是可以直接从表格中获取已经计算过的结果。这种使用了额外的存储空间来节省计算时间的方法,常被称为空间换时间。动态规划关键在于如何定义子问题和状态,如何寻找和计算状态转移。

动态规划主要包含三个步骤:

  • 定义状态:状态可以看做是原问题的子问题,通常是对应的一个或多个变量。例如,在背包问题中,状态就是当前放入背包的物品的总价值。

  • 状态转移方程:状态转移方程描述了状态之间的关系。例如,在背包问题中,当前的总价值可以由之前的物品价值和当前物品的价值得出。

  • 初始化和边界条件:动态规划解决问题时,需要一个初始状态作为问题的起点,并在问题解决的过程中处理好边界条件。

下面介绍五个经典的动态规划问题,以及它们的解决思路和代码表示:

  1. 斐波那契数列

这是最简单的动态规划问题,它描述的是一种特殊的数列:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2) (n>=2),要求出第n项的数值。

解题思路:假设dp[i]表示第i个斐波那契数,状态转移方程为dp[i] = dp[i-1] + dp[i-2]

vector<int> fib(int N) {
    vector<int> dp(N+1, 0);
    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. 凑零钱问题

这是一种找零问题,给定不同面额的硬币和一个总金额,每种硬币的数量无限,求出能拼凑出总金额所需的最少的硬币个数。

解题思路:假设dp[i]表示拼出金额i所需的最少硬币个数,状态转移方程为dp[i] = min(dp[i], dp[i-coin]+1)其中coin为所有硬币面额。

int coinChange(vector<int>& coins, int amount) {
    vector<int> dp(amount + 1, amount + 1);
    dp[0] = 0;
    for (int i = 1; i <= amount; i++) {
        for (int coin : coins) {
            if (coin <= i) {
                dp[i] = min(dp[i], dp[i - coin] + 1);
            }
        }
    }
    return dp[amount] > amount ? -1 : dp[amount];
}
  1. 最长公共子序列

给出两个字符串,求出他们的最长公共子序列的长度。

解题思路:假设dp[i][j]表示字符串1的前i个字符和字符串2的前j个字符的最长公共子序列的长度,当str1[i]==str2[j]时,dp[i][j]等于dp[i-1][j-1]+1,否则等于max(dp[i-1][j], dp[i][j-1])

int longestCommonSubsequence(string text1, string text2) {
    int m = text1.length(), n = text2.length();
    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];
}
  1. 0-1背包问题

这是一种很经典的动态规划问题,给定一组物品的重量和价值,一个能承受最大重量的背包,求出能装入背包的物品的最大价值。

解题思路:假设dp[i][j]表示前i个物品重量不超过j的最大价值,状态转移方程为dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])

int knapsack(vector<int>& weight, vector<int>& value, int W) {
    int n = weight.size();
    vector<vector<int>> dp(n+1, vector<int>(W+1, 0));
    
    for(int i = 1; i <= n; i++){
        for(int j = W; j >= 1; j--){
            if(j >= weight[i-1]){
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i-1]] + value[i-1]);
            }
            else{
                dp[i][j] = dp[i-1][j];
            }
        }
    }
    return dp[n][W];
}
  1. 最长递增子序列

给出一个无序的整数数组,求出它的最长递增子序列的长度。

解题思路:假设dp[i]表示以第i个数字结尾的最长上升子序列长度,状态转移方程为dp[i] = max(dp[i], dp[j] + 1)(对所有0<=j<i,如果nums[i]>nums[j])。

int lengthOfLIS(vector<int>& nums) {
    if (nums.empty())
        return 0;
    vector<int> dp(nums.size(), 1);
    int res = 1;
    for (int i = 1; i < nums.size(); ++i) {
        for (int j = 0; j < i; ++j) {
            if (nums[j] < nums[i]) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        res = max(res, dp[i]);
    }
    return res;
}

如果你想更深入地了解人工智能的其他方面,比如机器学习、深度学习、自然语言处理等等,也可以点击这个链接,我按照如下图所示的学习路线为大家整理了100多G的学习资源,基本涵盖了人工智能学习的所有内容,包括了目前人工智能领域最新顶会论文合集和丰富详细的项目实战资料,可以帮助你入门和进阶。

链接: 人工智能交流群【最新顶会与项目实战】(点击跳转)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1281004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBootAdmin

SpringBootAdmin 文章目录 SpringBootAdmin创建SpringBootAdmin服务端创建SpringBootAdmin客户端启动应用 总结 github地址 https://github.com/codecentric/spring-boot-admin 可以查到所有的版本号 创建SpringBootAdmin服务端 创建springBoot项目的时候&#xff0c;在ops选项…

图文并茂教你模拟302接口,实现js中axios,fetch遇到302状态码后跳转的多种方案axios,fetch成功响应拦截302

前情提要 日常工作中&#xff0c;我们会使用fetch,或者axios发起请求来获取数据&#xff0c;但是当我们遇到一些特殊需求的时候&#xff0c;使用不同库之后&#xff0c;会得到不同的结果&#xff0c;例如302,308的状态码&#xff0c;那么我们应该怎么处理这两种情况呢&#xf…

【Linux】第二十六站:软硬链接

文章目录 一、软链接二、硬链接三、ln命令四、该如何理解硬链接&#xff1f;五、如何理解软链接六、为什么要用软硬链接1.软链接的应用场景2.硬链接的应用场景 一、软链接 如下所示&#xff0c;我们创建一个文件以后&#xff0c;然后执行下面的指令 ln -s file.txt soft-link…

Prime 2.0

信息收集 # Nmap 7.94 scan initiated Thu Nov 23 20:09:06 2023 as: nmap -sn -oN live.nmap 192.168.182.0/24 Nmap scan report for 192.168.182.1 Host is up (0.00018s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for 192.168.182.2 Host is u…

P-Tuning v2论文概述

P-Tuning v2论文概述 P-Tuning v2论文概述前言微调的限制性P-Tuning的缺陷P-Tuning v2 摘要论文十问NLU任务优化点实验数据集预训练模型实验结果消融实验 结论 P-Tuning v2论文概述 前言 微调的限制性 微调&#xff08;fine-tuning&#xff09;是一种在预训练模型基础上进行目…

使用 Kettle 完成数据 ETL

文章目录 使用 Kettle 完成数据 ETL数据清洗数据处理 使用 Kettle 完成数据 ETL 现在我们有一份网站的日志数据集&#xff0c;准备使用Kettle进行数据ETL。先将数据集加载到Hadoop集群中&#xff0c;然后对数据进行清洗&#xff0c;最后加载到Hive中。 在本地新建一个数据集文…

Active Stereo Without Pattern Projector论文精读

1.背景补充 主动立体相机和被动立体相机的主要区别在于它们获取立体视觉信息的方式 主动立体相机12&#xff1a; 主动立体视觉是指寻找最佳的视角去重建目标或者场景1。主动视觉的实现方式通常有&#xff1a;改变环境中的光照条件、改变相机的视角、移动相机自身位置等&…

大模型中幂律缩放法则和涌现能力

幂律缩放法则是一种用于描述两个变量之间关系的数学模型。 根据幂律缩放法则&#xff0c;当一个变量的值变化时&#xff0c;另一个变量的值以指数方式变化。具体而言&#xff0c;幂律缩放法则可以表示为Y a * X^b&#xff0c;其中Y表示一个变量的值&#xff0c;X表示另一个变…

国民技术N32_MCU ADC如何获取高精度采样数据

前言 国民技术微控制器内置最多四个高级 12 位 ADC (取决于产品系列) &#xff0c;具有校准功能&#xff0c;用于提高环境条件 变化时的 ADC 精度。 在涉及模数转换的应用中&#xff0c; ADC 精度会影响整体的系统质量和效率。为了提高此精度&#xff0c;必须了解与 ADC 相关…

鸿蒙开发学习笔记

快速入门 配置网络权限 1.打开项目的 module.json5 文件 2.在module 里面写下面代码 3.这样就可以使用网络图片了 4.模拟器上就可以正常显示网络图片了 5.官方文档有相关说明 6. 华为官方编辑工具使用技巧&#xff08;内置文档&#xff09;&#xff0c;鼠标移动到标签上&…

JVM内存结构:StringTable与常量池关系

首先看一道题 这就涉及到StringTable和常量池&#xff0c;答案在文末&#xff0c;全做对就不用看了 而StringTable的位置在不同版本也有变化 &#xff0c; 我们只探讨jdk1.8版本 与StringTable 串池对应的是常量池 案例一、常量池和串池联系 引用所指肯定不会是常量池中的字…

实验6 二叉树操作

0x01 实验目的 掌握二叉树的基本概念&#xff0c;二叉树的存储结构使用链表。 0x02 实验内容 输入一个完全二叉树的层次遍历字符串&#xff0c;创建这个二叉树&#xff0c;输出这个二叉树的前序遍历字符串、中序遍历字符串、后序遍历字符串、结点数目、二叉树高度(上述每一个…

基于Java SSM框架+Vue实现旅游资源网站项目【项目源码+论文说明】

基于java的SSM框架Vue实现旅游资源网站演示 摘要 本论文主要论述了如何使用JAVA语言开发一个旅游资源网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述旅游…

notepad ++ 用法大全【程序员必会高级用法】

目录 1&#xff1a;notepad 介绍 2&#xff1a; 快捷键 3&#xff1a; notepad 实用插件 1&#xff1a;notepad 介绍 notepad是一款免费且开源的文本编辑器&#xff0c;可运行在Windows系统上。它支持多种编程语言&#xff0c;包括C、C、Java、Python等等。Notepad具有许多实…

Qt国际化翻译Linguist使用

QT的国际化是非常方便的&#xff0c;简单的说就是QT有自带的翻译工具把我们源代码中的字符串翻译成任何语言文件&#xff0c;再把这个语言文件加载到项目中就可以显示不同的语言。下面直接上手&#xff1a; 步骤一&#xff1a;打开pro文件&#xff0c;添加&#xff1a;TRANSLA…

Mysql安全之基础合规配置

一、背景 某次某平台进行安全性符合型评估时&#xff0c;列出了数据库相关安全选项&#xff0c;本文特对此记录&#xff0c;以供备忘参考。 二、安全配置 2.1、数据库系统登录时的用户进行身份标识和鉴别&#xff1b; 1&#xff09;对登录Mysql系统用户的密码复杂度是否有要…

MYSQL报错 [ERROR] InnoDB: Unable to create temporary file; errno: 0

起因 服务器的mysql不支持远程访问&#xff0c;在修改完相关配置后重启服务出错。 2023-12-03T10:12:23.895459Z 0 [Note] C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld.exe (mysqld 5.7.22-log) starting as process 15684 ... 2023-12-03T10:12:23.908886Z 0 [Note…

TimiGP细胞互作算法

介绍&#xff1a; 通过推断细胞间相互作用和免疫细胞预后价值来研究时间的计算方法。我们的方法将存活统计数据与批量转录组学图谱相结合&#xff0c;以构建免疫细胞-细胞相互作用网络&#xff0c;其中边缘&#xff08;例如&#xff0c;X → Y&#xff09;表明高 X/Y 比值与良…

unity学习笔记17

一、动画组件 Animation Animation组件是一种更传统的动画系统&#xff0c;它使用关键帧动画。你可以通过手动录制物体在时间轴上的变换来创建动画。 一些重要的属性&#xff1a; 1. 动画&#xff08;Animation&#xff09;&#xff1a; 类型&#xff1a; Animation组件允许…

React如何检查组件性能

可以使用Profiler来查看组件的渲染速度 Profiler的基本使用 需要将<Profiler>标签包裹在需要检查渲染速度的组件外部需要绑定id属性&#xff0c;该属性是唯一标识&#xff0c;用于区分其他Profiler需要onRender函数&#xff0c;该函数一共有六个参数&#xff0c;分别为…