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)是一种常用的解决方法。它通过将问题拆分为更小的子问题,并将子问题的解存储起来,避免了重复计算,从而提高算法的效率。动态规划的基本思想是利用已经计算过的子问题的解来计算更大规模的问题的解,这种思想被称为"最优子结构"。通过定义状态、状态转移方程和初始条件,我们可以构建动态规划算法。动态规划可以分为以下几个步骤:定义状态:明确问题需要求解的状态是什么,可以用一个或多个变量来表示。这些状态可以表示问题的规模、位置、限制条件等。确定状态转移方程:找到问题的递推关系,即将大规模问题的解表示为小规模问题的解。这需要根据问题的特点和已知信息建立数学模型。状态转移方程描述了问题从一个状态转移到另一个状态的方式。定义初始条件:确定最小规模的问题的解,即边界条件。这些初始条件可以是已知的问题解,或者根据问题的特点进行定义。使用迭代或递归的方式计算问题的解:根据状态转移方程,使用循环迭代或递归方式计算问题的解,并将中间结果保存起来,避免重复计算。输出结果:根据问题要求,输出最终求解得到的结果。动态规划在解决一些经典问题中非常有效,如背包问题、最长公共子序列问题、最短路径问题等。通过合理定义状态和状态转移方程,动态规划可以大大简化问题的求解过程,提高算法的效率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智慧公厕方案_智慧公厕解决方案_智慧公厕整体解决方案

一、什么是智慧公厕&#xff1f; 在现代城市化进程中&#xff0c;公共厕所是不可或缺的基础设施之一。然而&#xff0c;传统的公厕管理模式已经无法满足市民对高效、便捷厕所服务的需求。为了实现公共厕所的信息化管理&#xff0c;智慧公厕整体解决方案应运而生。智慧公厕具体…

查看pip当前关联python版本及位置

好久没用python了&#xff0c;把各种pip指向的环境忘光光啦&#xff0c;这里记录一下查看pip当前关联的python版本及位置的方法&#xff1a; pip -V结果&#xff1a; 我一般不用这个版本的python&#xff0c;去环境变量看了一下&#xff0c;原来是anaconda的Scripts自带pip&a…

Cisco Packet Tracer 模拟器实现一些交换机的基本配置

1. 内容 应用Cisco Packet Tracer 5.3搭建网络 应用Cisco Packet Tracer 5.3配置网络 通过不同的命令实现交换机的基本配置&#xff0c;包括交换机的各种配置模式、交换机的基本配置、交换机的端口配置。 2. 过程 2.1 打开软件 安装模拟器后打开如下&#xff1a; 图1 安装并…

揭秘数据中心幕后:从电力消耗到温度调控的策略

建设并运营数据中心并非简单的连接硬盘、通电和联网就可以&#xff0c;而是涉及复杂的硬件集成、能源管理、散热设计以及适应不断增长的数据处理和存储需求等诸多挑战。随着全球互联网的普及和AI技术的快速发展&#xff0c;数据中心的规模和能耗需求都在急剧增加。尤其是在电力…

找到零值点

clear clc close all fs200; t(1/200:1/200:30); signalsin(2*pi*0.1*t); LL1:1:length(t); figure(1) plot(LL,signal) zero_indices []; % 存储最靠近0的点的索引 start_indices []; % 存储开始点的索引 end_indices []; % 存储结束点的索引 for i 2:length(si…

Python算法(顺序查找/二分查找)

一。顺序查找法&#xff1a; 用途&#xff1a;主要用于查找无序的列表的某个元素 时间复杂度为O(n) 拓展&#xff1a;函数index&#xff08;&#xff09;运用的是顺序查找 二。二分查找法&#xff1a; 前提&#xff1a;被查找的列表顺序一定要是顺序的 用途&#xff1a;对…

软件测试 需求

文章目录 1. 需求1.1 什么是需求1.2 为什么要有需求1.3 测试人员眼中的需求1.4 如何深入理解需求 2. 测试用例的概念2.1 什么是测试用例2.2 为什么要有测试用例 3. 软件错误&#xff08;BUG&#xff09;的概念4. 开发模型和测试模型4.1 软件的生命周期4.2 瀑布模型&#xff08;…

SpringBoot集成netty实现websocket通信

实现推送消息给指定的用户 一、依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://m…

加密流量分类torch实践4:TrafficClassificationPandemonium项目更新

加密流量分类torch实践4&#xff1a;TrafficClassificationPandemonium项目更新 更新日志 代码已经推送开源至露露云的github&#xff0c;如果能帮助你&#xff0c;就给鼠鼠点一个star吧&#xff01;&#xff01;&#xff01; 3/10号更新 流量预处理更新 增加了基于splitCa…

加快代码审查的 7 个最佳实践

目录 前言 1-保持小的拉取请求 2-使用拉取请求模板 3-实施响应时间 SLA 4-培训初级和中级工程师 5-设置持续集成管道 6-使用拉取请求审查应用程序 7-生成图表以可视化您的代码更改 前言 代码审查可能会很痛苦软件工程师经常抱怨审查过程缓慢&#xff0c;延迟下游任务&…

Spring boot2.7整合jetcache 本地linkedhashmap缓存方案

好 上文 Spring boot2.7整合jetcache 远程redis缓存方案 我们讲完了 远程实现方案 本文 我们来说说 本地 jetcache解决方案 首先是 application.yml 在jetcache下加上 local:default:type: linkedhashmapkeyConvertor: fastjson我们技术用的 本地缓存 linkedhashmap 这里 我们…

conda 设置国内源 windows+linux

默认的conda源连接不好&#xff0c;时好时坏&#xff0c;而且速度很慢&#xff0c;可以使用国内的源 如果没有安装conda&#xff0c;可以参考&#xff1a; miniconda安装&#xff1a;链接 anaconda安装winlinux&#xff1a;链接 windows使用命令提示符&#xff0c;linux使用…

【C语言】glibc

一、获取源码 apt install glibc-source 在Debian系统中&#xff0c;通过apt install glibc-source命令安装的glibc源码通常会被放置在/usr/src/glibc目录下。安装完成后&#xff0c;可能需要解压缩该源码包。以下是解压缩源码包的步骤&#xff1a; 1. 打开终端。 2. 切换到源…

2024年【P气瓶充装】考试报名及P气瓶充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 P气瓶充装考试报名是安全生产模拟考试一点通总题库中生成的一套P气瓶充装复审考试&#xff0c;安全生产模拟考试一点通上P气瓶充装作业手机同步练习。2024年【P气瓶充装】考试报名及P气瓶充装复审考试 1、【多选题】《…

docker学习笔记——Dockerfile

Dockerfile是一个镜像描述文件&#xff0c;通过Dockerfile文件可以构建一个属于自己的镜像。 如何通过Dockerfile构建自己的镜像&#xff1a; 在指定位置创建一个Dockerfile文件&#xff0c;在文件中编写Dockerfile相关语法。 构建镜像&#xff0c;docker build -t aa:1.0 .(指…

esp32 idf.py cmd powershell 环境

esp32 idf.py cmd powershell 命令行 环境 win10 推荐使用 Windows Terminal 替换自己路径 设置–>添加新配置文件–>选择cmd 或者 powershell -->保存–> 去修改命令行 启动目录&#xff0c;推荐使用父进程目录 powershell C:\WINDOWS/System32/WindowsPowe…

【STA】SRAM / DDR SDRAM 接口时序约束学习记录

1. SRAM接口 相比于DDR SDRAM&#xff0c;SRAM接口数据与控制信号共享同一时钟。在用户逻辑&#xff08;这里记作DUA&#xff08;Design Under Analysis&#xff09;&#xff09;将数据写到SRAM中去的写周期中&#xff0c;数据和地址从DUA传送到SRAM中&#xff0c;并都在有效时…

关于查看 CentOS7虚拟机的 ip地址

1. 启动网卡 1.1 打开网卡配置文件。 vi /etc/sysconfig/network-scripts/ifcfg-eth01.2 启动网卡 修改为下图中的ONBOOTyes 2. 重启网络服务 sudo service network restart3. 查看ip地址 ip addr

NBlog整合OSS图库

NBlog部署维护流程记录&#xff08;持续更新&#xff09;&#xff1a;https://blog.csdn.net/qq_43349112/article/details/136129806 由于项目是fork的&#xff0c;所以我本身并不清楚哪里使用了图床&#xff0c;因此下面就是我熟悉项目期间边做边调整的。 目前已经调整的功能…

http协议分析

目录 一、实验目的 二、实验环境 三、实验步骤 四、实验数据记录和结果分析 五、实验体会、质疑和建议 一、实验目的 通过在真实网络环境访问HTTP服务器上网的过程中,捕获HTTP数据报文,分析报文的内容,掌握HTTP报文的构成,理解HTTP协议的工作过程&#xff0c; 二、实验环境…