动态规划—资源分配

概要

动态规划的决策不是线性的而是全面考虑到各种不同情况分别进行决策,最后通过多阶段决策逐步找出问题最优解。而当前决策也会依赖于上一阶段的决策,此时便会发生状态的转移。动态规划算法可以说是一种“聪明的蛮力法”,因为动态规划是会考虑到每一种可能,而聪明的地方是相对于蛮力法,它去掉了很多没必要的运算。

 

 例1、资源分配问题

现有7万元需要投资到A,B,C三个项目,利润表如下图。求总利润分配最大的资源分配方案

 1234567
A0.110.130.150.210.240.300.35
B0.120.160.210.230.250.240.34
C0.080.120.200.240.260.300.35

 

#include <iostream>
using namespace std;
int main(){
	
	double invest[3][8]={//投资表,记录了A,B,C三个投资的利润率信息,预留多一个位置,invest[i][j]中i表示项目,j表示金额 
						{0,0.11,0.13,0.15,0.21,0.24,0.30,0.36},
						{0,0.12,0.16,0.21,0.23,0.25,0.24,0.34},
						{0,0.08,0.12,0.20,0.24,0.26,0.30,0.35}
						};
	double max[8],temp[8]={0},gain[8]={0};//max记录的是优策略下的投资利润率,gain记录的是当前投资金额可得的最大利润
	//temp记录的是上一次决策中可以获得的最大利润 
	for(int i=0;i<8;i++){//初始化,当只有A投资可选时,最优投资策略便是全部投资A 
		max[i]=invest[0][i];
	}
	
	for(int i=0;i<8;i++){//初始化,当只有A投资可选时,可以得到的最大利润
		gain[i]=invest[0][i]*i;
	}	 
	
	for(int i=1;i<3;i++){//控制投资项目 
		for(int j=1;j<8;j++){//控制投资金额,j即为当前的投资金额
			for(int k=0;k<j;k++){//k表示投资给上一个最优决策的金额, j-k表示把剩余的资金投资给新添加的那个项目 
				temp[j]=max[k]*k+invest[i][j-k]*(j-k); 
				if(gain[j]<temp[j]){
					gain[j]=temp[j];
					max[j]=gain[j]/j;
				}				
			}
		}
	}
	//输出 
	cout<<"最大投资利润率为:"; 
	for(int i=1;i<8;i++){
		cout<<max[i]<<" ";
	} 
	cout<<endl<<"最大利润为:";
	for(int i=1;i<8;i++){
		cout<<gain[i]<<" ";
	} 	
}

 

实验课程:算法分析与设计 实验名称:用动态规划法求解资源分配问题 (验证型实验) 实验目标: (1)掌握用动态规划方法求解实际问题的基本思路。 (2)进一步理解动态规划方法的实质,巩固设计动态规划算法的基本步骤。 实验任务: (1)设计动态规划算法求解资源分配问题,给出算法的非形式描述。 (2) 在Windows环境下用C 语言实现该算法。计算10个实例,每个实例中n=30, m=10, Ci j为随机产生于范围(0,103)内的整数。记录各实例的数据及执行结果(即最优分配方案、最优分配方案的值)、运行时间。 (3)从理论上分析算法的时间和空间复杂度,并由此解释相应的实验结果。 实验设备及环境: PC;C/C++等编程语言。 实验主要步骤: (1) 根据实验目标,明确实验的具体任务; (2) 分析资源分配问题,获得计算其最优值的递推计算公式; (3) 设计求解问题动态规划算法,并编写程序实现算法; (4) 设计实验数据并运行程序、记录运行的结果; (5) 分析算法的时间和空间复杂度,并由此解释释相应的实验结果; 问题分析: 问题描述: 某厂根据计划安排,拟将n台相同的设备分配给m个车间,各车间获得这种设备后,可以为国家提供盈利Ci j(i台设备提供给j号车间将得到的利润,1≤i≤n,1≤j≤m) 。问如何分配,才使国家得到最大的盈利? 算法基本思想: 本问题是一简单资源分配问题,由于具有明显的最优子结构,故可以使用动态规划求解,用状态量f[i][j]表示用i台设备分配给前j个车间的最大获利,那么显然有f[i][j] = max{ f[k][j–1] + c[i-k][j] },0<=k<=i。再用p[i][j]表示获得最优解时第j号车间使用的设备数为i-p[i][j],于是从结果倒推往回求即可得到分配方案。程序实现时使用顺推,先枚举车间数,再枚举设备数,再枚举状态转移时用到的设备数,简单3重for循环语句即可完成。时间复杂度为O(n^2*m),空间复杂度为O(n*m),倘若此题只需求最大获利而不必求方案,则状态量可以减少一维,空间复杂度优化为O(n)。
### 动态规划资源分配问题中的应用 动态规划是一种解决多阶段决策过程最优化问题的有效方法,其核心思想是通过把原问题分解为相对简单的子问题的方式求解复杂问题。对于资源分配问题而言,动态规划可以通过构建状态转移方程来实现最优解的获取。 #### 1. 资源分配问题描述 假设存在有限数量的某种资源 $ R $ 和多个任务 $ T_1, T_2, \ldots, T_n $ 需要这些资源的支持。每个任务 $ T_i $ 对应一定的收益函数 $ f(x) $,其中 $ x $ 表示分配给该任务的资源量。目标是在总资源约束下最大化整体收益。 此问题可以用动态规划建模并求解[^1]。 #### 2. 状态定义与递推关系 设 $ dp[i][j] $ 表示前 $ i $ 个任务,在可用资源总量为 $ j $ 的情况下所能获得的最大收益,则有如下递推关系: $$ dp[i][j] = \max(dp[i-1][j], dp[i-1][j-k] + f(k)) $$ 其中: - $ k $ 是第 $ i $ 个任务可能被分配到的资源量; - $ dp[i-1][j] $ 表示不将任何额外资源分配给当前任务的情况下的最大收益; - $ dp[i-1][j-k] + f(k) $ 则表示将部分资源 $ k $ 分配给当前任务后的最大收益。 边界条件通常设定为当无剩余资源或者未处理任何任务时,收益均为零 ($ dp[0][j]=0 $ 或者 $ dp[i][0]=0 $)[^2]。 #### 3. 实现代码示例 以下是基于上述理论的一个简单 Python 实现例子: ```python def resource_allocation(total_resource, tasks): n = len(tasks) dp = [[0]*(total_resource+1) for _ in range(n+1)] for i in range(1, n+1): task_benefit_func, max_task_resource = tasks[i-1] for j in range(0, total_resource+1): if j >= max_task_resource: dp[i][j] = max( dp[i-1][j], dp[i-1][j-max_task_resource] + task_benefit_func(max_task_resource) ) else: dp[i][j] = dp[i-1][j] return dp[n][total_resource] # Example usage with a simple benefit function and maximum resources per task. tasks = [ (lambda r: r * 5, 2), # Task 1 has linear gain up to 2 units of resource (lambda r: r ** 2, 3) # Task 2 has quadratic gain up to 3 units of resource ] print(resource_allocation(4, tasks)) # Output the optimal allocation result ``` #### 4. 结果解释 以上程序实现了如何利用动态规划找到一种最佳方式去分配固定数目的资源至不同任务上以达到最高总体效益的目的。具体来说,它遍历每种可能性,并记录下每一个中间步骤的最佳方案直到最终得出全局最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值