数据结构与算法:动态规划的深度探讨

news2025/1/13 10:24:35

目录

12.1 动态规划的核心思想

12.2 经典动态规划问题

12.3 动态规划在图中的应用

12.4 高级动态规划技术

总结


数据结构与算法:动态规划的深度探讨

动态规划(Dynamic Programming, DP)是一种解决复杂问题的有效方法,特别适用于那些可以被分解为重叠子问题的场景。通过使用动态规划,我们可以显著减少解决某些问题的时间复杂度。本章将探讨动态规划的核心思想、经典问题、在图中的应用以及高级技术。

12.1 动态规划的核心思想

动态规划的核心思想是将问题分解为多个子问题,通过记忆化存储或表格化存储避免重复计算,从而提高计算效率。

最优子结构与子问题重叠的细致分析

  • 最优子结构:问题的最优解由其子问题的最优解构成。

  • 子问题重叠:问题在求解过程中会出现许多相同的子问题。

核心思想说明
最优子结构问题可以分解为子问题,子问题的最优解组合构成问题的最优解
子问题重叠解决问题时会反复计算相同的子问题

代码示例:斐波那契数列的动态规划实现

#include <stdio.h>
#define MAX 100

int fibonacci(int n) {
    int dp[MAX];
    dp[0] = 0;
    dp[1] = 1;
    for (int i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}

int main() {
    int num = 10;
    printf("斐波那契数列的第 %d 项是 %d\n", num, fibonacci(num));
    return 0;
}

在上述代码中,通过数组 dp 记录中间计算结果,避免了递归中的重复计算问题,从而将时间复杂度降到 O(n)。

自顶向下与自底向上的策略:动态规划有两种实现策略:

  • 自顶向下(记忆化搜索):通过递归的方式解决问题,并用数组或字典存储已计算的结果。

  • 自底向上(表格法):直接从最小的子问题开始,逐步计算出最终问题的解。

策略优势劣势
自顶向下代码简单,容易理解递归栈开销大
自底向上无递归开销,性能稳定需要设计表格结构,稍显复杂

12.2 经典动态规划问题

动态规划可以解决多种经典的组合优化问题,下面是一些典型例子:

背包问题的多种变体与时间优化:背包问题是动态规划中的经典问题,包含01背包、完全背包、多重背包等多种变体。

代码示例:01背包问题的实现

#include <stdio.h>
#define MAX_WEIGHT 50
#define MAX_ITEMS 4

int knapsack(int weights[], int values[], int n, int maxWeight) {
    int dp[MAX_ITEMS + 1][MAX_WEIGHT + 1] = {0};
    for (int i = 1; i <= n; i++) {
        for (int w = 0; w <= maxWeight; w++) {
            if (weights[i - 1] <= w) {
                dp[i][w] = (values[i - 1] + dp[i - 1][w - weights[i - 1]] > dp[i - 1][w]) ?
                            (values[i - 1] + dp[i - 1][w - weights[i - 1]]) : dp[i - 1][w];
            } else {
                dp[i][w] = dp[i - 1][w];
            }
        }
    }
    return dp[n][maxWeight];
}

int main() {
    int weights[] = {10, 20, 30};
    int values[] = {60, 100, 120};
    int maxWeight = 50;
    printf("最大价值: %d\n", knapsack(weights, values, 3, maxWeight));
    return 0;
}

在01背包问题中,利用二维数组 dp 存储每个物品在不同重量限制下的最大价值,从而实现优化。

最长公共子序列(LCS)问题与复杂度分析:LCS 问题用于求解两个字符串的最长公共子序列长度,是一个典型的动态规划问题。

问题类型示例时间复杂度
背包问题最大化装入背包物品的总价值O(n * W)
最长公共子序列两个字符串最长相同的子序列长度O(m * n)

12.3 动态规划在图中的应用

动态规划在图中的应用非常广泛,尤其是在路径问题上。最短路径、多源最短路径等问题都可以使用动态规划来求解。

Floyd-Warshall算法与多源最短路径:Floyd-Warshall 算法用于求解图中任意两点之间的最短路径,适用于带权图,并且权值可以为负数。

代码示例:Floyd-Warshall算法实现

#include <stdio.h>
#define INF 99999
#define V 4

void floydWarshall(int graph[][V]) {
    int dist[V][V];
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            dist[i][j] = graph[i][j];
        }
    }
    for (int k = 0; k < V; k++) {
        for (int i = 0; i < V; i++) {
            for (int j = 0; j < V; j++) {
                if (dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }
    printf("最短路径矩阵:\n");
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            if (dist[i][j] == INF)
                printf("INF ");
            else
                printf("%d ", dist[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int graph[V][V] = {
        {0, 3, INF, 7},
        {8, 0, 2, INF},
        {5, INF, 0, 1},
        {2, INF, INF, 0}
    };
    floydWarshall(graph);
    return 0;
}

在该代码中,通过动态规划实现了 Floyd-Warshall 算法,可以有效地求解所有节点之间的最短路径。

12.4 高级动态规划技术

状态压缩与空间优化:对于某些问题,可以通过状态压缩来减少空间复杂度。例如,在01背包问题中,可以使用一维数组代替二维数组,从而将空间复杂度从 O(n * W) 降到 O(W)。

动态规划与树形DP、区间DP的结合

  • 树形DP:适用于树结构的动态规划问题,通过在树的节点上进行自底向上的计算,求解最优值。

  • 区间DP:适用于需要在区间上进行操作的问题,例如矩阵链乘问题,通过将区间逐步扩大,求解最优解。

高级技术适用场景优势
状态压缩减少动态规划的空间复杂度降低空间占用
树形DP树结构上的最优问题利用树的天然层次结构
区间DP区间合并、分割的优化问题逐步扩大区间,减少重复计算

代码示例:状态压缩的背包问题实现

#include <stdio.h>
#define MAX_WEIGHT 50
#define MAX_ITEMS 3

int knapsackOptimized(int weights[], int values[], int n, int maxWeight) {
    int dp[MAX_WEIGHT + 1] = {0};
    for (int i = 0; i < n; i++) {
        for (int w = maxWeight; w >= weights[i]; w--) {
            if (dp[w] < values[i] + dp[w - weights[i]]) {
                dp[w] = values[i] + dp[w - weights[i]];
            }
        }
    }
    return dp[maxWeight];
}

int main() {
    int weights[] = {10, 20, 30};
    int values[] = {60, 100, 120};
    int maxWeight = 50;
    printf("最大价值 (空间优化): %d\n", knapsackOptimized(weights, values, MAX_ITEMS, maxWeight));
    return 0;
}

在该代码中,使用状态压缩将空间复杂度从二维降低到一维,从而显著节省了内存空间。

总结

本章深入讨论了动态规划的基本思想、经典问题、在图中的应用及其高级技术。动态规划通过将问题分解为子问题,并通过记忆化存储减少计算次数,从而有效地解决了许多复杂的优化问题。通过理解最优子结构、重叠子问题,以及不同实现策略,我们可以更加高效地解决实际问题。

在下一章中,我们将探讨搜索与优化技术,包括回溯与分支限界等内容,进一步提高问题求解的效率。

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

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

相关文章

Nuxt3部署-Ubuntu系统(Node 服务 + pm2 + Nginx 反向代理)

Nuxt3部署-Ubuntu系统&#xff08;Node 服务 pm2 Nginx 反向代理&#xff09; 文章目录 Nuxt3部署-Ubuntu系统&#xff08;Node 服务 pm2 Nginx 反向代理&#xff09;一、安装 Nodejs 环境二、安装 Nginx三、安装 pm2四、本地项目打包1️⃣&#xff1a;打包2️⃣&#xff1…

【截流软件】采集短视频关键词笔记下的筛选评论

用python开发的dy采集工具【爬抖Y搜索评论软件】&#xff0c;可用于引流截流等。 支持2种模式的评论采集&#xff1a; 根据关键词采集评论&#xff0c;爬取思路&#xff1a;作品关键词->作品链接->评论根据作品链接采集评论&#xff0c;爬取思路&#xff1a;作品链接-&g…

aws(学习笔记第六课) AWS的虚拟私有,共有子网以及ACL,定义公网碉堡主机子网以及varnish反向代理

aws(学习笔记第六课) AWS的虚拟私有&#xff0c;共有子网以及ACL&#xff0c;定义公网碉堡主机子网以及varnish反向代理 学习内容&#xff1a; AWS的虚拟私有&#xff0c;共有子网以及ACL定义公网碉堡主机子网&#xff0c;私有子网和共有子网以及varnish反向代理 1. AWS的虚拟…

分享一个中国行政区划多边形2024版(含有十段线)

全国省市县三级行政区划分类 全国有省市县界限数据 十段线 有需要自取

[Linux系统编程] 线程同步(互斥锁,读写锁,死锁,条件变量,信号量)

一.线程同步概念 线程同步&#xff1a; 协同步调&#xff0c;对公共区域数据按序互斥访问。防止数据混乱&#xff0c;产生与时间有关的错误。 数据混乱的原因&#xff1a; 1.资源共享(独享资源则不会) 2.调度随机(意味着数据访问会出现竞争)—线程间竞争 3.线程间缺乏必要同步…

一篇闪击常用放大器电路(学习笔记)

文章目录 声明概念名词经典电路分析反向放大器同向放大器加法器减法器积分电路微分电路差分放大电路电流->电压转换电路电压->电流转换电路 虚短与虚断一、虚短二、虚断 一些碎碎念 声明 ​ 本文是主要基于以下两篇博客所做的笔记&#xff1a; 模电四&#xff1a;基本放…

图论day60|108.冗余连接(卡码网) 、109.冗余连接II(卡码网)【并查集 摧毁信心的一题,胆小的走开!】

图论day60|108.冗余连接&#xff08;卡码网&#xff09;、109.冗余连接II&#xff08;卡码网&#xff09;【并查集 摧毁信心的一题&#xff0c;胆小的走开&#xff01;】 108.冗余连接&#xff08;卡码网&#xff09;109.冗余连接II&#xff08;卡码网&#xff09;【并查集 摧毁…

Flythings学习(四)串口通信

文章目录 1 串口编程基本步骤1.1 打开串口1.2 配置串口 1.3 读串口1.4 发送串口1.5 关闭串口 2 综合使用3 如何在软件上保证串口稳定通信4 flythings中的串口通讯5 协议接收部分使用和修改方法6 通讯协议数据怎么和UI控件对接 1 串口编程基本步骤 串口通信有5个步骤 1.打开串口…

【干货】Ftrans跨网数据摆渡系统,如何实现网间数据安全高效流转?

随着企业数字化转型的逐步深入&#xff0c;企业投入了大量资源进行信息系统建设&#xff0c;信息化程度日益提升。在这一过程中&#xff0c;企业也越来越重视核心数据资产的保护&#xff0c;数据资产的安全防护成为企业面临的重大挑战。 一、网络隔离的必要性 绝大多数企业为…

步进电机定时器与编码器定时器关系

速度环PID比较计数器的增量公式&#xff1a; 位置环PID比较计数器的增量公式&#xff1a;

【 香格里拉酒店-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

gitLab配置ssh

1打开git命令行&#xff0c;创建秘钥 ssh-keygen -t rsa -b 4096 -C "用户名xxx.com" 2执行下面的命令查看公钥 cat ~/.ssh/id_rsa.pub 3#复制公钥到gitlab网址上ssh页面添加ssh的key&#xff08;公钥&#xff09; 4本地的git命令行中添加账户邮箱 git config -…

Centos安装Nginx 非Docker

客户的机器属于 Centos7 系列&#xff0c;由于其较为陈旧&#xff0c;2024开始众多镜像和软件源都已失效。此篇文章将详细记录在 Centos7 操作系统上从零开始安装 Nginx 的整个流程。 本文Nginx是安装在/usr/local/nginx下 详细步骤如下&#xff1a; 准备Nginx安装包&#x…

ABB高性能矢量型变频器ACS380的性能优势

ABB ACS380变频器是一款可靠、易用、灵活的高性能矢量型变频器&#xff0c;其优异的电机控制、耐久的设计以及与所有主要工业自动化网络的连接性而成为各类设备电机驱动的理想之选。 1. 广泛的功率范围 ABB ACS380 变频器拥有广泛的功率输出区间&#xff0c;在单项 230V 电压下…

springboot员工管理系统-计算机毕业设计源码35173

目 录 1 绪论 1.1 研究背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 系统流程…

第三方软件测评机构分享:软件性能测试方法

软件性能测试指测试人员通过各种手段检测产品是否符合性能指标、评估系统服务能力和完成系统优化的测试活动&#xff0c;专业第三方软件测评机构卓码软件测评简要分享以下几种性能测试方法&#xff1a; 1.压力测试   通过对软件系统不断施加压力&#xff0c;识别系统性能拐…

07 django管理系统 - 部门管理 - 搜索部门

在dept_list.html中&#xff0c;添加搜索框 <div class"container-fluid"><div style"margin-bottom: 10px" class"clearfix"><div class"panel panel-default"><!-- Default panel contents --><div clas…

工程文件参考——STM32+HAL+SPI主从机通讯

文章目录 前言CubeMX设置SPI设置NSS设置 SPI从机代码SPI主机代码 前言 关于如何简单的写一个稳定的SPI主从机通讯&#xff0c;思路很简单 1、SPI高速传输的时候很容易出现错位之类的问题&#xff0c;CRC的校验首先是必要的。在STM32中SPI使用DMA通讯可以自动执行CRC的校验&…

路由器原理和静态路由配置

一、路由器的工作原理 根据路由表转发数据 接收数据包→查看目的地址→与路由表进行匹配找到转发端口→转发到该端口 二、路由表的形成 它是路由器中维护的路由条目的集合&#xff0c;路由器根据路由表做路径选择&#xff0c;里面记录了网段ip地址和对应下一跳接口的接口号。…