AHU 算法分析 实验四 动态规划

实验四:动态规划

实验目的

• 理解动态规划的基本思想,理解动态规划算法的两个基本要素最 优子结构性质和子问题的重叠性质。

• 熟练掌握典型的动态规划问题。

• 掌握动态规划思想分析问题的一般方法,对较简单的问题能正确 分析,设计出动态规划算法,并能快速编程实现。

钢条切割问题

有一段长度为n的钢条,钢条可以被分割成不同的长度的小钢 条出售,不同的小钢条对应不同的售价。详见下表:

钢条长度012345678910
价格p01589101717202424

钢条切割问题是这样的: 给定⼀段长度为n的钢条和⼀个价格表 pi(i=1,2,…n), 求切割钢条⽅案, 使得销售收益最⼤。 注意, 如果长度为n英⼨的钢条的价格pn⾜够⼤, 最优解可能就是完全不需 要切割。

输入:钢条的长度n,不同长度钢条的价值Pi,{i=1,…,n}

输入:1、最大收益,2、切割方案。

问题分析

我们选用一个状态方程去描述问题,设f(i,j)为状态方程,含义是在0~i种可被切割长度,j为当前钢条长度,举例f(3,5)意思就是在当前长度为5的时候,钢条可被切成0,1,2,3,这几种长度。

当我们不选择第i种切割方式时,那么还剩i-1种切割方式,所以有状态转移方程
f ( i , j ) = f ( i − 1 , j ) f( i,j)=f(i-1,j) f(i,j)=f(i1,j)
当我们选择第i种切割方式的时候,如果此时 i > j i>j i>j, 那么应该放弃这种方案,即状态转移方程为
f ( i , j ) = f ( i − 1 , j ) f(i,j)=f(i-1,j) f(i,j)=f(i1,j)
如果此时 i < = j i<=j i<=j, 因为这种方式可能被选择多次,所以我们选择k次来表示,以不失一般性,那么状态转移方程为
f ( i , j ) = m a x ( ∑ k = 0 + ∞ f ( i − 1 , j − k ∗ i ) + k ∗ a [ i ] ) f(i,j)=max(\sum_{k=0}^{+\infty}f(i-1,j-k*i)+k*a[i]) f(i,j)=max(k=0+f(i1,jki)+ka[i])
然后将选择第i种方案合并,即状态转移方程为
f ( i , j ) = m a x ( f ( i − 1 , j ) , ∑ k = 0 + ∞ f ( i − 1 , j − k ∗ i ) + k ∗ a [ i ] ) f(i,j)=max(f(i-1,j), \ \sum_{k=0}^{+\infty}f(i-1,j-k*i)+k*a[i]) f(i,j)=max(f(i1,j), k=0+f(i1,jki)+ka[i])
这里我们进行一个数学方程的变换
f ( i , j − i ) = m a x ( ∑ k = 0 + ∞ f ( i − 1 , j − ( k + 1 ) ∗ i ) + k ∗ a [ i ] ) f(i,j-i)=max(\sum_{k=0}^{+\infty}f(i-1,j-(k+1)*i)+k*a[i]) f(i,ji)=max(k=0+f(i1,j(k+1)i)+ka[i])
可以将两个式子联立
f ( i , j ) = m a x ( f ( i − 1 , j ) , f ( i , j − i ) + a [ i ] ) f(i,j)=max(f(i-1,j),\ f(i,j-i)+a[i]) f(i,j)=max(f(i1,j), f(i,ji)+a[i])
分析完毕

源代码

#include <iostream>
using namespace std;int a[1000];
int dp[1000][1000];
int x[1000];int fun(int len) {for (int i = 1; i <=len; i++) {for (int j = 0; j <=len; j++) {dp[i][j]=dp[i-1][j];if(j>=i)dp[i][j] = max(dp[i-1][j], dp[i][j - i] + a[i]);}}return dp[len][len];
}void traceback(int j, int y)
{while (j) {while (y < j) {j--;}if (dp[j][y] == (dp[j][y - j] + a[j]))                                  {x[j]++;y = y - j;++j;}j--;}
}
int main(){int len = 0;int sum = 0;bool flag=1;cin >> len;for (int i = 1; i <= len; i++) {scanf("%d", &a[i]);}cout << fun(len)<<endl;traceback(len, len);cout << "切割方案为:将长度为" << len << "的钢条切割成";for (int i = 1; i <= len; i++) {while (x[i]--) {cout << i << "  ";sum = sum + a[i];}}cout << "\n最大收益为" << sum;return 0;
}

然后可以优化代码,让空间复杂度减小一倍

int a[1000];
int dp[1000];
int x[1000];int fun(int len) {for (int i = 1; i <=len; i++) {for (int j =i; j <=len; j++) {dp[j] = max(dp[j], dp[j - i] + a[i]);}}return dp[len];
}void traceback(int j, int y)
{while (j) {while (y < j) {j--;}if (dp[y] == (dp[y - j] + a[j]))                                  {x[j]++;y = y - j;++j;}j--;}
}
int main(){int len = 0;int sum = 0;bool flag=1;cin >> len;for (int i = 1; i <= len; i++) {scanf("%d", &a[i]);}cout << fun(len)<<endl;traceback(len, len);cout << "切割方案为:将长度为" << len << "的钢条切割成";for (int i = 1; i <= len; i++) {while (x[i]--) {cout << i << "  ";sum = sum + a[i];}}cout << "\n最大收益为" << sum;return 0;
}

结果演示

在这里插入图片描述

实验总结

在写这个实验的时候,刚开始我使用了递归的方法,然后由于递归比较难回溯,所以改进算法,使用了动态规划,这道题我研究调试代码很长时间,虽然耗费很久,但是通过这次实验我对动态规划掌握更进一步,还是让我受益良多。当面对一些具有重叠子问题性质的问题时,动态规划(Dynamic Programming)是一种常用的解决方法。它通过将问题拆分为更小的子问题,并将子问题的解存储起来,避免了重复计算,从而提高算法的效率。动态规划的基本思想是利用已经计算过的子问题的解来计算更大规模的问题的解,这种思想被称为"最优子结构"。通过定义状态、状态转移方程和初始条件,我们可以构建动态规划算法。动态规划可以分为以下几个步骤:定义状态:明确问题需要求解的状态是什么,可以用一个或多个变量来表示。这些状态可以表示问题的规模、位置、限制条件等。确定状态转移方程:找到问题的递推关系,即将大规模问题的解表示为小规模问题的解。这需要根据问题的特点和已知信息建立数学模型。状态转移方程描述了问题从一个状态转移到另一个状态的方式。定义初始条件:确定最小规模的问题的解,即边界条件。这些初始条件可以是已知的问题解,或者根据问题的特点进行定义。使用迭代或递归的方式计算问题的解:根据状态转移方程,使用循环迭代或递归方式计算问题的解,并将中间结果保存起来,避免重复计算。输出结果:根据问题要求,输出最终求解得到的结果。动态规划在解决一些经典问题中非常有效,如背包问题、最长公共子序列问题、最短路径问题等。通过合理定义状态和状态转移方程,动态规划可以大大简化问题的求解过程,提高算法的效率。

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

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

相关文章

网络故障基本判断方法

1&#xff09;电脑上使用winR键&#xff0c;打开运行窗口&#xff0c;输入CMD命令&#xff0c;点击回车键 2&#xff09;在弹出的CMD运行窗口中输入ipconfig命令 通过该命令可以查看本机的IP地址&#xff0c;子网掩码和网关等信息。确认电脑中所有网卡配置是否正确。 3&…

llc稳压基本思路2

这套控制思路实际上就是开关电源中常见的反馈系统 大致思路就是&#xff0c;如果由于其他参数波动引起了输出电压偏差&#xff0c;我们可以直接监测这个输出电压&#xff0c;然后根据输出电压与目标电压值的偏差信号传输给芯片&#xff0c;然后芯片来改变频率&#xff0c;从而改…

前端学习之行内和块级标签

行内标签 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>span</title> </head> <body><!-- 行内标签特点&#xff1a;1、不换行,一行可以放多个2、默认宽度内容撑开代表&#…

Googlenet网络架构

原文链接&#xff1a;[1409.4842v1] Going Deeper with Convolutions (arxiv.org) 图源&#xff1a;深入解读GoogLeNet网络结构&#xff08;附代码实现&#xff09;-CSDN博客 表截自原文 以下&#x1f4d2;来自博客深入解读GoogLeNet网络结构&#xff08;附代码实现&#xff0…

【顶刊|修正】多区域综合能源系统热网建模及系统运行优化【复现+延伸】

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该程序复现《多区域综合能源系统热网建模及系统运行优化》模型并进一步延伸&#xff0c;基于传热学的基本原理建立了区域热网能量传输通用模型&#xff0c;对热网热损方程线性化实现热网能量流建模&#xff0…

使用docker-compose编排ruoyi项目

目录 一、开始部署 1.拉取ruoyi代码 2.拉取node镜像 3.拉取maven镜像 4.在/root/ruoyi/java下写一个Dockerfile用于后端Java环境 5.拉取MySQL&#xff0c;Redis&#xff0c;Nginx镜像 6.在/root/java目录下写一个nginx.conf 7.在/root/ruoyi目录下写docker-compose.yml文…

Idea导入Maven项目

方法一&#xff1a;使用Maven面板 方法二&#xff1a;在项目结构中设置&#xff0c;在最后一步中选择pom.xml。

前端学习之列表标签

目录 有序列表 结果 无序标签 结果 数据标签 结果 有序列表 &#xff08;注&#xff1a;注释是解释&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title> </…

【JavaEE初阶系列】——计算机是如何工作的

目录 &#x1f388;冯诺依曼体系 ❗外存和内存的概念 ❗CPU中央处理器—人类当今科技领域巅峰之作之一 &#x1f6a9;如何衡量cpu &#x1f6a9;指令&#xff08;Instruction&#xff09; &#x1f388;操作系统&#xff08;Operating System&#xff09; &#x1f388;…

关于GPU显卡的介绍

一.关于英伟达历代产品架构 显卡是一种计算机硬件设备,也被称为显示适配器或图形处理器。目前的硬件部分主要由主板、芯片、存储器、散热器&#xff08;散热片、风扇&#xff09;等部分。显卡的主要芯片是显卡的主要处理单元。显卡上也有和计算机存储器相似的存储器&#xff0…

安全测试报告-模板内容

1. 概述 为检验XXXX平台 系统的安全性&#xff0c;于 XXXX年 XX 月 XX 日至 XXXX年 XX 月 XX日对目标系统进行了安全测试。在此期间测试人员将使用各 种非破坏性质的攻击手段&#xff0c;对目标系统做深入的探测分析&#xff0c;进而挖掘系统中的安 全漏洞和风险隐患。研发团队…

代码讲解:如何把3D数据转换成旋转的视频?

目录 3D数据集下载 读取binvox文件 使用matplotlib创建图 动画效果 完整代码 3D数据集下载 这里以shapenet数据集为例&#xff0c;可以访问外网的可以去直接申请下载&#xff1b;我也准备了一个备份在百度网盘的数据集&#xff0c;可以参考&#xff1a; ShapeNet简介和下…

Vue3中Vue Router的使用区别

在 Vue 3 中&#xff0c;useRouter 和 useRoute 是两个用于 Vue Router 的 Composition API 函数&#xff0c;它们的用途和返回的对象不同&#xff0c;接下来详细了解一下它们的区别以及如何正确使用它们。 useRouter useRouter 用于获取 router 实例&#xff0c;这个实例提供…

macOS14.4安装FFmpeg及编译FFmpeg源码

下载二进制及源码包 二进制 使用brew安装ffmpeg : brew install ffmpeg 成功更新到ffmpeg6.1 下载FFmpeg源码

LVS (Linux Virtual server)集群介绍

一 集群和分布式 &#xff08;一&#xff09;系统性能扩展方式&#xff1a; Scale UP&#xff1a;垂直扩展&#xff0c;向上扩展,增强&#xff0c;性能更强的计算机运行同样的服务 &#xff08;即升级单机的硬件设备&#xff09; Scale Out&#xff1a;水平扩展&#xff0…

Anaconda prompt运行打开jupyter notebook 指令出错解决方案

一、打不开jupyter notebook网页 报错如下&#xff1a; Traceback (most recent call last): File “D:\anaconda3\lib\site-packages\notebook\traittypes.py”, line 235, in _resolve_classes klass self._resolve_string(klass) File “C:\Users\DELL\AppData\Roaming\Py…

单文件组件SFC及Vue CLI脚手架的安装使用

单文件组件SFC及Vue CLI脚手架的安装使用 Vue 单文件组件&#xff08;又名 *.vue 文件&#xff0c;缩写为 SFC&#xff09;是一种特殊的文件格式&#xff0c;它允许将 Vue 组件的模板、逻辑 与 样式封装在单个文件中。 为什么要使用 SFC 使用 SFC 必须使用构建工具&#xff…

Vue class和style绑定:动态美化你的组件

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

考研经验|如何从考研失败中走出来?

对我来说&#xff0c;太丢人了 其实我在本科的时候在同学眼中&#xff0c;一直很优秀&#xff0c;每年奖学金必有我的&#xff0c;国家励志奖学金&#xff0c;国家奖学金&#xff0c;这种非常难拿的奖学金&#xff0c;我也拿过&#xff0c;本科期间学校有一个公费去新西兰留学的…

Text Field文本输入框

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Text Field文本输入框 一、最基本的本文输入框1、基础示例2、一些表单属性3、验证 二、多行文本 一、最基本的本文输入框 1、基础示例 import {Box, TextField} from "…