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.hqwc.cn/news/527962.html

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

相关文章

云上攻防-云产品篇堡垒机场景JumpServer绿盟SASTeleport麒麟齐治

知识点 1、云产品-堡垒机-产品介绍&攻击事件 2、云产品-堡垒机-安全漏洞&影响产品 章节点&#xff1a; 云场景攻防&#xff1a;公有云&#xff0c;私有云&#xff0c;混合云&#xff0c;虚拟化集群&#xff0c;云桌面等 云厂商攻防&#xff1a;阿里云&#xff0c;腾讯…

2024 年广东省职业院校技能大赛(高职组) “云计算应用”赛项样题①

2024 年广东省职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项样题① 模块一 私有云&#xff08;50 分&#xff09;任务 1 私有云服务搭建&#xff08;10 分&#xff09;任务 2 私有云服务运维&#xff08;25 分&#xff09;任务 3 私有云运维开发&#xf…

多项式回归算法模拟

import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.preprocessing import PolynomialFeatures# 生成随机数作为x变量&#xff0c;范围在-5到5之间&#xff0c;共500个样本 x np.random.uniform(-5, 5, siz…

LCR 131. 砍竹子 I

解题思路&#xff1a;&#xff08;与砍竹子II的区别是&#xff0c;这里的竹子长度数量级较小&#xff09; 数学推导或贪心 切分规则&#xff1a; 等长&#xff0c;且尽量为3 b0时&#xff0c;pow(3,a) b1时&#xff0c;pow(3,a-1)*4 少一段3&#xff0c;并入b生成一…

蓝桥杯练习题——归并排序

1.火柴排队 思路 1.求最小值的时候&#xff0c;可以直接按升序排序&#xff0c;这样得到的值就是最小值 2.求最小交换次数的时候&#xff0c;不能直接排序&#xff0c;因为只能交换相邻的数&#xff0c;只需要知道他们的相对大小&#xff0c;所以可以先用离散化&#xff0c;把…

Springboot+vue的医院药品管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的医院药品管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

熵值法测算面板数据的影响因素权重,怎么计算?是全部扔进去还是分省份分年份?

结论 计算的权重略有区别&#xff0c;个别可能比较大&#xff1b;计算的综合指标差异不大&#xff0c;但趋势一致。反思&#xff1a;如果嫌麻烦&#xff0c;那就全扔进去。因为面板的个体差异和时间差异&#xff0c;如果很看重权重&#xff0c;那还是分开计算好。最后&#xf…

IDEA打开项目文件目录不见了

偶尔发生新拉下来的代码&#xff0c;或者旧代码修改了包名&#xff0c;项目名称等&#xff0c;idea左侧project一栏不显示代码的文件目录。例如下面此时不要慌张&#xff0c;不用删除项目重新拉取&#xff0c;通过以下方式解决&#xff1a; 本人尝试能够解决&#xff0c;如果无…

Javaweb之Maven高级之聚合的详细解析

2.2 聚合 分模块设计与开发之后啊&#xff0c;我们的项目被拆分为多个模块&#xff0c;而模块之间的关系&#xff0c;可能错综复杂。 那就比如我们当前的案例项目&#xff0c;结构如下&#xff08;相对还是比较简单的&#xff09;&#xff1a; 此时&#xff0c;tlias-web-mana…

Long-term Correlation Tracking LCT 目标跟踪算法源码运行

资源 LCT-tracker项目地址VLFeat官网OpenCV下载地址OTB50数据集百度网盘资源 参考博客 一步一步教你跑lct-tracker&#xff08;Win10Matlab 2016bVisual Studio 2015&#xff09;LCT代码跑起来先文章思路总结 正文 1. 环境配置 我的环境&#xff1a;Win11、Visual Studio…

编译支持国密的抓包工具 WireShark

目录 前言WireShark支持国密的 WireShark小结前言 在上一篇文章支持国密的 Web 服务器中,我们搭建了支持国密的 Web 服务器,但是,我们使用 360 安全浏览器去访问,却出现了错误: 是我们的 Web 服务器没有配置好?在这里插入图片描述还是 360 安全浏览器不支持国密?还是两…

【三两波折】指向函数的指针

函数占用内存&#xff0c;在虚拟内存中属于txt段&#xff08;只读&#xff09;&#xff0c;函数也是有地址的。 函数指针的定义&#xff1a; (返回值类型)(*函数指针名)(参数列表) 当我们调用Proc函数时&#xff0c;一般写作&#xff1a; double ans Proc(6, 7.8f); 实际上是C…