动态规划求解投资最优问题

1. 问题

  • 一般性描述:
    • m m m 元钱, n n n 项投资项目,函数 f i f_{i} fi 表示将 x x x 元投入第i项项目所产生的效益, i = 1 , 2 , ⋅ ⋅ ⋅ , n i=1,2,···,n i=1,2n
      问:如何分配这 m m m 元钱,使得投资总效益最高?
  • 组合优化问题:
    • 假设分配给第i个项目的钱数是 x i x_{i} xi
    • 目标函数: m a x ( f 1 ( x 1 ) + f 2 ( x 2 ) + ⋅ ⋅ ⋅ + f n ( x n ) ) max({f_1(x_1)+ f_2(x_2)+···+ fn(x_n)}) max(f1(x1)+f2(x2)++fn(xn))
    • 约束条件: x 1 + x 2 + x 3 + ⋅ ⋅ ⋅ + x n = m , x i ∈ n x_1+x_2+x_3+···+x_n=m, xi∈n x1+x2+x3++xn=m,xin

2. 解析

给定投资效益表 ( m = 5 , n = 4 ) (m = 5, n = 4) m=5,n=4

投资 x x x效益 f 1 ( x ) f_{1}(x) f1(x) f 2 ( x ) f_{2}(x) f2(x) f 3 ( x ) f_{3}(x) f3(x) f 4 ( x ) f_{4}(x) f4(x)
00000
1110220
21251021
313103022
414153223
515204024

手动推算结果:

  • F k ( x ) F_k(x) Fk(x) 表示 x x x 元投资给前 k k k 个项目的最大收益, k ∈ [ 1 , 2 , . . . , n ] k∈[1,2,...,n] k[1,2,...,n]
  • x k ( y ) x_k(y) xk(y) 表示 y y y 元投资给第 k k k 个项目, k ∈ [ 1 , 2 , . . . , n ] k∈[1,2,...,n] k[1,2,...,n]
投资 X X X F 1 ( x ) F_1(x) F1(x) x 1 ( x ) x_1(x) x1(x) F 2 ( x ) F_2(x) F2(x) x 2 ( x ) x_2(x) x2(x) F 3 ( x ) F_3(x) F3(x) x 3 ( x ) x_3(x) x3(x) F 4 ( x ) F_4(x) F4(x) x 4 ( x ) x_4(x) x4(x)
1111110110201
2122120131311
3133162303331
4144213413501
5155264434611
  • 黄色区域为选择最优结果,分别投资项目1、项目3和项目4以1元、3元、1元可得最大收益61。

3. 设计

动态规划求解投资问题

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;

int n,m,x;
int f[N][N],F[N][N];

void run() {
	cin>>n>>m;
	for (int j=0;j<=m;j++) {
		for (int i=1;i<=n;i++) {
			cin>>f[i][j];
		}
	}
    //枚举投资
	for (int i=1;i<=n;i++) {
        //枚举前i个共分配j元
		for (int j=0;j<=m;j++) {
            //枚举第i个投资投资k元
			for (int k=0;k<=j;k++) {
				F[i][j] = max(F[i][j],F[i-1][j-k] + f[i][k]);
			}
		}
	}
	printf("mx = %d\n",F[n][m]);
}

int main() {
	run();
	return 0;
}

/*
4 5
0 0 0 0 
11 0 2 20
12 5 10 21
13 10 30 22
14 15 32 23
15 20 40 24

*/

4. 分析

  • F k ( x ) = m a x ( f k ( x k ) + F k − 1 ( x − x k ) ) F_k(x) = max(f_k(x_k)+F_{k-1}(x-x_k)) Fk(x)=max(fk(xk)+Fk1(xxk))
  • x i ∈ [ 0 , . . . , x ] xi∈[0,...,x] xi[0,...,x] 共x+1项, f k ( x k ) + F k − 1 ( x − x k ) f_k(x_k)+F_{k-1}(x-x_k) fk(xk)+Fk1(xxk) 有x+1项,因此有x+1次加,x次比较大小
  • 加法 ∑ k = 2 n ∑ x = 1 m ( x + 1 ) = ( n − 1 ) ∗ m ∗ ( m + 3 ) 2 \sum_{k=2}^{n}\sum_{x=1}^{m}(x+1)=\frac{(n-1)*m*(m+3)}{2} k=2nx=1m(x+1)=2(n1)m(m+3)
  • 比较 ∑ k = 2 n ∑ x = 1 m x = ( n − 1 ) ∗ m ∗ ( m + 1 ) 2 \sum_{k=2}^{n}\sum_{x=1}^{m}x=\frac{(n-1)*m*(m+1)}{2} k=2nx=1mx=2(n1)m(m+1)
  • T ( n , m ) = O ( n ∗ m 2 ) T(n,m) = O(n*m^2) T(n,m)=O(nm2)

5. 源码

https://github.com/a894985555/Algorithm/tree/main/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E6%8A%95%E8%B5%84%E9%97%AE%E9%A2%98

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划是一种常用的解决优化问题的方法,可以用来解决投资问题。在投资问题中,我们需要在给定的一组投资选项中选择最佳的投资组合,以最大化收益或者最小化风险。 动态规划解决投资问题的一般步骤如下: 1. 定义状态:首先需要定义问题的状态。在投资问题中,状态可以表示为投资的时间点、可选的投资选项等。 2. 定义状态转移方程:根据问题的特点,定义状态之间的转移关系。在投资问题中,状态转移方程可以表示为当前时间点的最优投资收益与前一个时间点的最优投资收益之间的关系。 3. 初始化:初始化初始状态,即第一个时间点的状态。 4. 递推计算:根据状态转移方程,逐步计算出每个时间点的最优投资收益。 5. 回溯求解:根据计算得到的最优投资收益,回溯找到对应的最优投资组合。 下面是一个简单的例子来说明动态规划如何实现投资问题: 假设有3个投资选项,分别是股票、债券和房地产。每个选项在不同时间点的收益如下表所示: | 时间点 | 股票 | 债券 | 房地产 | |-------|------|------|--------| | 1 | 10% | 5% | 2% | | 2 | 5% | 3% | 8% | | 3 | 8% | 2% | 6% | 我们的目标是在每个时间点选择一个投资选项,使得最终的收益最大化。 根据上述步骤,我们可以进行如下计算: 1. 定义状态:我们可以定义状态为时间点和可选的投资选项。 2. 定义状态转移方程:假设dp[i][j]表示在第i个时间点选择第j个投资选项的最优投资收益,则状态转移方程可以表示为dp[i][j] = max(dp[i-1][k] * 收益率[i][j]),其中k表示前一个时间点的投资选项。 3. 初始化:初始化第一个时间点的状态,即dp[j] = 收益率[j]。 4. 递推计算:根据状态转移方程,逐步计算出每个时间点的最优投资收益。 5. 回溯求解:根据计算得到的最优投资收益,回溯找到对应的最优投资组合

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值