【动态规划案例】详细介绍投资问题

目录

投资问题描述

动态规划分析

案例分析

第一阶段

第二阶段

第三阶段

第四阶段

代码实现


投资问题描述

现有m万元资金,n个项目投资,假设:x_{i}为分配给第i个项目的资金;f_{i}(x_{i})为第i个项目投资得到的收益(万元)。问:如何投资使得总效益最大?

动态规划分析

根据动态规划的一般性步骤,首先建立目标函数和约束条件,根据上面假设得到:

目标函数:F=max{\sum_{i=1}^{n}}f_{i}(x_{i});

约束条件:\begin{cases} \sum_{i=1}^{n}x_{i}\leqslant m \\ x_{i}\geqslant 0,i=1,2,...,n \end{cases};

假设F_{k}(x)x万元钱投资给前k个项目获得的最大收益,用动态规划思路求解,问题就转成求F_{k}(m)

k=1时,也就是说只投一个项目时最大收益为:

F_{k}(x)=f_{1}(x)

1<k\leqslant n时,即至少投资两个项目以上时,设p0\leqslant p\leqslant x)为分配给第k个项目的资金,此时还剩下x-p的资金可分配给前k-1个项目,则获得的最大收益为:

f_{k}(p)+F_{k-1}(x-p)

根据上面的分析,可以得到转移方程:

F_{k}(x)=\begin{cases} max\{f_{k}(p)+F_{k-1}(x-p)\}, 0\leqslant p\leqslant x\&\&0<k\leqslant n\\ f_{1}(x),k=1\end{cases}

案例分析

以上得到的转移方程分析比较理论话,下面用一个例子来做一下案例分析,比较直观和容易理解。

设某机构有60万元准备投资给4个项目,每个项目获得的收益和投资金额如下所示:

 根据问题要求,求出F_{4}(60)

第一阶段

k=1时,只投资一个项目,那么显然得到F_{1}(x)=f_{1}(x),当投资金额x=0,10,20,30,40,50,60时分别计算得到如下结果: 

最优策略展示表格如下:

投资金额x0102030405060
最优策略(0)(10)(20)(30)(40)(50)(60)

此时投资金额60万元的最优投资策略为:F_{1}(60)=f_{1}(60)=85,即(60)。

第二阶段

k=2时,此时需要考虑前两个项目投资情况下获得的最大收益,即F_{2}(x)=max\{F_{1}(x-p)+f_{2}(p)\},下面公式展现了当投资金额x=60,p=\{0,10,20,30,40,50,60\}时求最优策略过程:

 F_{2}(60)=max\begin{Bmatrix} F_{1}(0)+f_{2}(60)\\ F_{1}(10)+f_{2}(50)\\ F_{1}(20)+f_{2}(40)\\ F_{1}(30)+f_{2}(30)\\ F_{1}(40)+f_{2}(20)\\ F_{1}(50)+f_{2}(10)\\ F_{1}(60)+f_{2}(0)\\ \end{Bmatrix}=max\begin{Bmatrix} 0+65\\ 20+60\\ 50+55\\ 65+50\\ 80+40\\ 85+20\\ 85+0\\ \end{Bmatrix}=120,投资金额x=60的最优投资策略为(40,20)。同理,

F_{2}(50)=max\begin{Bmatrix} F_{1}(0)+f_{2}(50)\\ F_{1}(10)+f_{2}(40)\\ F_{1}(20)+f_{2}(30)\\ F_{1}(30)+f_{2}(20)\\ F_{1}(40)+f_{2}(10)\\ F_{1}(50)+f_{2}(0)\\ \end{Bmatrix}=max\begin{Bmatrix} 0+60\\ 20+55\\ 50+55\\ 65+40\\ 80+20\\ 85+0\\ \end{Bmatrix}=105,投资金额x=50的最优投资策略为(30,20)。

F_{2}(40)=max\begin{Bmatrix} F_{1}(0)+f_{2}(40)\\ F_{1}(10)+f_{2}(30)\\ F_{1}(20)+f_{2}(20)\\ F_{1}(30)+f_{2}(10)\\ F_{1}(40)+f_{2}(0)\\ \end{Bmatrix}=max\begin{Bmatrix} 0+55\\ 20+50\\ 50+40\\ 65+20\\ 80+0\\ \end{Bmatrix}=90,投资金额x=40的最优投资策略为(20,20)。

依此类推,可以求得F_{2}(30),F_{2}(20),F_{2}(10),F_{2}(0)。最终展示如下:

对应的最优投资策略如下表格所示:

投资金额x0102030405060
最优策略(0,0)

(10,0)

(0,10)

(20,0)(20,10)(20,20)(30,20)(40,20)

第三阶段

k=3时,此时就需要考虑前三个项目都投资情况下获得的最大收益,即F_{3}(x)=max\{F_{2}(x-p)+f_{3}(p)\},当投资金额x=60,p=\{0,10,20,30,40,50,60\}时求最优策略:

F_{3}(60)=max\begin{Bmatrix} F_{2}(0)+f_{3}(60)\\ F_{2}(10)+f_{3}(50)\\ F_{2}(20)+f_{3}(40)\\ F_{2}(30)+f_{3}(30)\\ F_{2}(40)+f_{3}(20)\\ F_{2}(50)+f_{3}(10)\\ F_{2}(60)+f_{3}(0)\\ \end{Bmatrix}=max\begin{Bmatrix} 0+115\\ 20+110\\ 50+100\\ 70+85\\ 90+60\\ 105+25\\ 120+0\\ \end{Bmatrix}=155,投资金额x=60的最优投资策略为(20,10,30)。

依此类推,可以求得F_{3}(50),F_{3}(40),F_{3}(30),F_{3}(20),F_{3}(10),F_{3}(0),最终结果如下: 

对应的最优投资策略如下表格所示:

投资金额x0102030405060
最优策略(0,0,0)

(0,0,10)

(0,0,20)(0,0,30)(20,0,20)(20,0,30)(20,10,20)

第四阶段

k=4时,此时4个项目获得的最大收益,即F_{4}(x)=max\{F_{3}(x-p)+f_{4}(p)\},当投资金额x=60,p=\{0,10,20,30,40,50,60\}时求最优策略:

 F_{4}(60)=max\begin{Bmatrix} F_{3}(0)+f_{4}(60)\\ F_{3}(10)+f_{4}(50)\\ F_{3}(20)+f_{4}(40)\\ F_{3}(30)+f_{4}(30)\\ F_{3}(40)+f_{4}(20)\\ F_{3}(50)+f_{4}(10)\\ F_{3}(60)+f_{4}(0)\\ \end{Bmatrix}=max\begin{Bmatrix} 70+0\\ 65+25\\ 60+60\\ 50+85\\ 40+110\\ 25+135\\ 0+155\\ \end{Bmatrix}=160

当投资金额为60时,投资4个项目最大收益为160万元,最优投资策略为(20,0,30,10)。

代码实现

var M = 60; // 投资总金额
var N = 4; // 投资项目数量
var LR = [ // 投资4个项目的收益
    [0, 20, 50, 65, 80, 85, 85],
    [0, 20, 40, 50, 55, 60, 65],
    [0, 25, 60, 85, 100, 110, 115],
    [0, 25, 40, 50, 60, 65, 70]
];
function dptz() {
    var F = [];
    var m = LR[0].length;
    var n = N;
    for (var i = 1; i <= n; i++) { // 按照项目循环
        F[i - 1] = [];
        for (var j = 0; j < m; j++) { // 按照总投资金额
            if (i == 1) {
                F[i - 1][j] = LR[i - 1][j];
            } else {
                var tmp = 0;
                for (var k = 0; k <= j; k++) {
                    tmp = Math.max(tmp, F[i - 2][k] + LR[i - 1][j - k]);
                }
                F[i - 1][j] = tmp;
            }
        }
    }
    console.log(F[N-1][len-1]); // 160
}
dptz();

通过代码可以看出有三个for循环,所以时间复杂度为O(nm^2)。求出最大收益没什么难度,关键是如何输出最大收益策略呢?代码优化如下:

var M = 60; // 投资总金额
var N = 4; // 投资项目数量
var LR = [ // 投资4个项目的收益
    [0, 20, 50, 65, 80, 85, 85],
    [0, 20, 40, 50, 55, 60, 65],
    [0, 25, 60, 85, 100, 110, 115],
    [0, 25, 40, 50, 60, 65, 70]
];
function dptz() {
    var F = [];
    var mem = []; // 保存当前总金额下,投资项目数的最优策略
    var m = LR[0].length;
    var n = N;
    for (var i = 1; i <= N; i++) {
        F[i - 1] = [];
        mem[i - 1] = [];
        for (var j = 0; j < m; j++) {
            if (i == 1) {
                F[i - 1][j] = LR[i - 1][j];
                mem[i - 1][j] = [j * 10];
            } else {
                var tmp = 0;
                var f = 0; // 当前项目分配的金额
                var TF = 0; // 剩余金额投资最优解的下标
                for (var k = 0; k <= j; k++) {
                    // tmp = Math.max(tmp, F[i - 2][k] + LR[i - 1][j - k]);
                    // var Fcur = k * 10;
                    // var fcur = M - Fcur;
                    if (F[i - 2][k] + LR[i - 1][j - k] >= tmp) {
                        tmp = F[i - 2][k] + LR[i - 1][j - k];
                        f = (j - k) * 10; // 当前项目分配的金额
                        TF = k; // 保存剩余金额k*10(通过j*10-f得到)时的最优解下标
                    }
                }
                F[i - 1][j] = tmp;
                mem[i - 1][j] = [];
                mem[i - 2][TF].forEach(el => { // 将剩余金额TF*10下的最优解赋值给当前项目下的最优解
                    mem[i - 1][j].push(el);
                })
                // mem[i - 1][j] = [...mem[i - 2][TF], f];
                // 将当前最优解保存起来,f就是当前项目i的投资金额数。
                mem[i - 1][j].push(f);
            }
        }
    }
    console.log(F[N - 1][m - 1]);
    console.log(mem[N - 1][m - 1])
}
dptz();

运行得出了最大收益和最优策略方案:

  • 10
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值