本文利用markdown基于https://blog.csdn.net/qq_41926985/article/details/105627049重写,代码部分为本人编辑
代码要求
应用动态规划方法,求解投资问题,实现下面的例子。
#define MAX_N 4 //最大投资项目数目
#define MAX_M 5 //最大投资钱数(万元)
//f[i][j]的意义:第 i(从 1 开始)个项目投资 j 万元的收益
int f[MAX_N+1][MAX_M+1] = {
    {0,0,0,0,0,0},
    {0,11,12,13,14,15},
    {0,0,5,10,15,20},
    {0,2,10,30,32,40},
    {0,20,21,22,23,24}
}; 
投资问题
什么是投资问题
有 m m m元钱, n n n项投资, f i ( x ) f_i(x) fi(x):将x元投入第i个项目的效益。求使得的总效益最大的投资方案。
举个例子:现在有两个项目x是钱数(单位:元),
f i ( x ) f_i(x) fi(x):将x元钱投资到第i个项目产生的效益
注意:使用的是总共的x钱数投资两个项目,而不是分别投资。

将0元投资这两个项目,则最大收益就是0
将1元投资这两个项目,不难看出
f 1 ( 1 ) + f 2 ( 0 ) = 11 f_1(1)+f_2(0)=11 f1(1)+f2(0)=11
,是最大收益
将2元投资这两个项目,不难看出
f 1 ( 2 ) + f 2 ( 0 ) = 12 f_1(2)+f_2(0)=12 f1(2)+f2(0)=12
,是最大收益
将3元投资这两个项目,
m a x ( f 1 ( 0 ) + f 2 ( 3 ) , f 1 ( 1 ) + f 2 ( 2 ) , f 1 ( 2 ) + f 2 ( 1 ) , f 1 ( 3 ) + f 2 ( 0 ) ) = f 1 ( 1 ) + f 2 ( 2 ) = 16 max(f_1(0)+f_2(3),f_1(1)+f_2(2),f_1(2)+f_2(1),f_1(3)+f_2(0)) =f_1(1)+f_2(2)=16 max(f1(0)+f2(3),f1(1)+f2(2),f1(2)+f2(1),f1(3)+f2(0))=f1(1)+f2(2)=16
,是最大收益
同样的用4元或者5元投资这两个项目,所带来的最大收益分别是21和26
我们接下来对问题进行建模:
目标函数:利用所分配的投资产生最大效益
约束条件:是在总资金的条件下进行投资

建模:
问题的解是向量 < x 1 , x 2 , ⋅ ⋅ ⋅ , x n > <x_1,x_2,···,x_n> <x1,x2,⋅⋅⋅,xn>
x i x_i xi是投给项目的钱数, i = 1 , 2 , ⋅ ⋅ ⋅ , n . i=1,2,···,n. i=1,2,⋅⋅⋅,n.
目标函数 m a x { f 1 ( x 1 ) + f 2 ( x 2 ) + ⋅ ⋅ ⋅ + f n ( x n ) } max \{f_1(x_1)+f_2(x_2)+···+f_n(x_n)\} max{f1(x1)+f2(x2)+⋅⋅⋅+fn(xn)}
约束条件: x 1 + x 2 + ⋅ ⋅ ⋅ + x n = m , x i ∈ N x_1+x_2+···+x_n=m,x_i\in N x1+x2+⋅⋅⋅+xn=m,xi∈N
下面我们来考虑用动态规划算法来解投资问题
动态规划算法来解投资问题
子问题的界定:由参数 k k k和 x x x界定
k k k:考虑对每个项目 1 , 2 , … , k 1,2,…,k 1,2,…,k的投资
x x x:投资总钱数不超过 x x x的
接下来我们再看一下递推方程
设 F k ( x ) : x F_k(x):x Fk(x):x元钱投给前k个项目的最大效益
我们可以这么想,假如我们要求 F k ( x ) F_k(x) Fk(x),即就是求x元钱投给前 k k k个项目的最大效益。那不妨求 p p p元钱 ( p ≤ x ) (p\leq x) (p≤x)投给前k-1个项目的最大效益 F k − 1 ( p ) F_{k-1}(p) Fk−1(p),进而确定 F k ( x ) F_k(x) Fk(x)
我们进而可以列出递推方程:

我们看到啊, 
     
      
       
        
        
          F 
         
        
          k 
         
        
       
         ( 
        
       
         x 
        
       
         ) 
        
       
      
        F_k(x) 
       
      
    Fk(x)的求解,就是去求用 
     
      
       
       
         x 
        
       
         − 
        
        
        
          x 
         
        
          k 
         
        
       
      
        x-x_k 
       
      
    x−xk分配前 
     
      
       
       
         k 
        
       
         − 
        
       
         1 
        
       
      
        k-1 
       
      
    k−1个项目所产生的最大效益。然而这个最大效益是在备忘录存着来。没错备忘录的作用就是存储最大的效益。
  
     
      
       
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         x 
        
       
         ) 
        
       
      
        F_1(x) 
       
      
    F1(x):就是在投资表中的用x钱投资第一个项目的收益
接下来我们看个例子:
 这是一个投资——效益表

我们要先明确最小子问题是什么,然后才能从这个最小子问题开始算起;然后考虑计算顺序,保证后面的值在前面已经计算好。
这里我们看到第一个项目的最大收益就是投资对应的收益,即
  
      
       
        
         
          
          
           
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             0 
            
           
             ) 
            
           
             = 
            
           
             0 
            
           
             , 
            
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             1 
            
           
             ) 
            
           
             = 
            
           
             11 
            
           
             , 
            
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             2 
            
           
             ) 
            
           
             = 
            
           
             12 
            
           
             , 
            
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             3 
            
           
             ) 
            
           
             = 
            
           
             13 
            
           
             , 
            
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             4 
            
           
             ) 
            
           
             = 
            
           
             14 
            
           
             , 
            
            
            
              F 
             
            
              1 
             
            
           
             ( 
            
           
             5 
            
           
             ) 
            
           
             = 
            
           
             15 
            
           
             。 
            
           
          
          
          
          
            (1) 
           
          
         
        
       
         F_1(0)=0,F_1(1)=11,F_1(2)=12,F_1(3)=13,F_1(4)=14,F_1(5)=15。\tag{1} 
        
       
     F1(0)=0,F1(1)=11,F1(2)=12,F1(3)=13,F1(4)=14,F1(5)=15。(1)
我们能看到啊,前1个项目可以定为最小子问题,它的初值可以通过查表得到,不用计算。而后面的项目随着项目的增多,子问题的复杂性就会增强。因此我们根据项目序列的递增关系来计算,从而保证后面的值在前面已经计算好了。
我们通过上面的递推方程可以得知,用 x − x k x-x_k x−xk分配前 k − 1 k-1 k−1个项目所产生的最大效益越大以及x元钱投给前k个项目的最大效益越大,从而使得原问题的解达到最大。进而满足依赖关系。而对于 x k x_k xk为何值,这个是需要通过计算获取最优解来得到。
好,我们来继续看前两个项目的最大效益:
 我们先看 
     
      
       
       
         x 
        
       
         = 
        
       
         0 
        
       
      
        x=0 
       
      
    x=0,则最大效益是0
再来看 
     
      
       
        
        
          x 
         
        
          k 
         
        
       
         = 
        
       
         1 
        
       
      
        x_k=1 
       
      
    xk=1, 
     
      
       
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         = 
        
       
         m 
        
       
         a 
        
       
         x 
        
       
         { 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         1 
        
       
         − 
        
       
         1 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         0 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         1 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         } 
        
       
         = 
        
       
         11 
        
       
      
        F_2(1)=max\{f_2(1)+F_1(1-1),f_2(0)+F_1(1-0)\}=11 
       
      
    F2(1)=max{f2(1)+F1(1−1),f2(0)+F1(1−0)}=11
 再来看 
     
      
       
        
        
          x 
         
        
          k 
         
        
       
         = 
        
       
         2 
        
       
      
        x_k=2 
       
      
    xk=2, 
     
      
       
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         2 
        
       
         ) 
        
       
         = 
        
       
         m 
        
       
         a 
        
       
         x 
        
       
         { 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         2 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         2 
        
       
         − 
        
       
         2 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         2 
        
       
         − 
        
       
         1 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         0 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         2 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         } 
        
       
         = 
        
       
         12 
        
       
      
        F_2(2)=max\{f_2(2)+F_1(2-2),f_2(1)+F_1(2-1),f_2(0)+F_1(2-0)\}=12 
       
      
    F2(2)=max{f2(2)+F1(2−2),f2(1)+F1(2−1),f2(0)+F1(2−0)}=12
 再来看 
     
      
       
        
        
          x 
         
        
          k 
         
        
       
         = 
        
       
         3 
        
       
      
        x_k=3 
       
      
    xk=3, 
     
      
       
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         3 
        
       
         ) 
        
       
         = 
        
       
         m 
        
       
         a 
        
       
         x 
        
       
         { 
        
       
         f 
        
       
         2 
        
       
         ( 
        
       
         3 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         3 
        
       
         − 
        
       
         3 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         2 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         3 
        
       
         − 
        
       
         2 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         3 
        
       
         − 
        
       
         1 
        
       
         ) 
        
       
         , 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         0 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         3 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         } 
        
       
         = 
        
       
         16 
        
       
      
        F_2(3)=max\{f2(3)+F_1(3-3),f_2(2)+F_1(3-2),f_2(1)+F_1(3-1),f_2(0)+F_1(3-0)\}=16 
       
      
    F2(3)=max{f2(3)+F1(3−3),f2(2)+F1(3−2),f2(1)+F1(3−1),f2(0)+F1(3−0)}=16
 同样的 
     
      
       
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         4 
        
       
         ) 
        
       
         = 
        
       
         21 
        
       
         , 
        
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         5 
        
       
         ) 
        
       
         = 
        
       
         26 
        
       
      
        F_2(4)=21,F_2(5)=26 
       
      
    F2(4)=21,F2(5)=26
当然,这里得到的 F 2 ( 1 ) , F 2 ( 2 ) , F 2 ( 3 ) , F 2 ( 4 ) , F 2 ( 5 ) F_2(1),F_2(2),F_2(3),F_2(4),F_2(5) F2(1),F2(2),F2(3),F2(4),F2(5)要记录到备忘录里面。
那么如何去记录解?
 我们用 
     
      
       
       
         s 
        
       
      
        s 
       
      
    s数组来记录解。我们去记录在得到最大效益的时候,最后一个项目给了多少钱。
 就如同上面的例子,在前两个项目的最大收益中。
  
     
      
       
        
        
          x 
         
        
          i 
         
        
       
         ( 
        
       
         x 
        
       
         ) 
        
       
         : 
        
       
      
        x_i(x): 
       
      
    xi(x):分配x元钱给前i个项目,在最大收益时,第i个项目得到了多少钱
  
     
      
       
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         : 
        
       
      
        x_2(1): 
       
      
    x2(1):看到啊, 
     
      
       
        
        
          F 
         
        
          2 
         
        
       
         ( 
        
       
         1 
        
       
         ) 
        
       
         = 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         0 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         1 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         = 
        
       
         11 
        
       
      
        F_2(1)=f_2(0)+F_1(1-0)=11 
       
      
    F2(1)=f2(0)+F1(1−0)=11。此时,第2个项目得到了0元钱
  
     
      
       
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         2 
        
       
         ) 
        
       
         : 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         0 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         2 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         = 
        
       
         12 
        
       
      
        x_2(2):f_2(0)+F_1(2-0)=12 
       
      
    x2(2):f2(0)+F1(2−0)=12。此时,第2个项目得到了0元钱
  
     
      
       
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         3 
        
       
         ) 
        
       
         : 
        
        
        
          f 
         
        
          2 
         
        
       
         ( 
        
       
         2 
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          1 
         
        
       
         ( 
        
       
         3 
        
       
         − 
        
       
         2 
        
       
         ) 
        
       
         = 
        
       
         16 
        
       
      
        x_2(3):f_2(2)+F_1(3-2)=16 
       
      
    x2(3):f2(2)+F1(3−2)=16。此时,第2个项目得到了2元钱
 同样的,我们也能得到 
     
      
       
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         4 
        
       
         ) 
        
       
         = 
        
       
         3 
        
       
         , 
        
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         5 
        
       
         ) 
        
       
         = 
        
       
         4 
        
       
      
        x_2(4)=3,x_2(5)=4 
       
      
    x2(4)=3,x2(5)=4
ok,下面介绍一下如何追踪解
 上面的投资问题的结果如图所示:

我们细想,原问题是用5元钱分配所有项目(这里就是4个项目),所得到的最大收益
 这个最大收益是不是就是 
     
      
       
        
        
          F 
         
        
          4 
         
        
       
         ( 
        
       
         5 
        
       
         ) 
        
       
      
        F_4(5) 
       
      
    F4(5)
 ( 
     
      
       
        
        
          F 
         
        
          4 
         
        
       
         ( 
        
       
         5 
        
       
         ) 
        
       
      
        F_4(5) 
       
      
    F4(5):用5元钱分配前4个项目得到的最大收益)
 ,那这个值就可以去衡量原问题的解。因此我们追踪解也要从 
     
      
       
        
        
          x 
         
        
          4 
         
        
       
         ( 
        
       
         5 
        
       
         ) 
        
       
      
        x_4(5) 
       
      
    x4(5)开始,自底向上追踪。
先看到x4(5)=1,说明达到最大收益的时候分配给最后一个项目,即第4个项目是1元钱。
 那么第3个项目呢?
 第3个项目就是 
     
      
       
        
        
          x 
         
        
          3 
         
        
       
         ( 
        
       
         x 
        
       
         ) 
        
       
      
        x_3(x) 
       
      
    x3(x),这个x就是5-1=4,就是用总共的5元钱-分配给第4个项目的钱数。
  
     
      
       
        
        
          x 
         
        
          3 
         
        
       
         ( 
        
       
         5 
        
       
         − 
        
       
         1 
        
       
         ) 
        
       
         = 
        
       
         3 
        
       
      
        x_3(5-1)=3 
       
      
    x3(5−1)=3。因此在得到最大收益时,分配给第3个项目3元钱。
 同理 
     
      
       
        
        
          x 
         
        
          2 
         
        
       
         ( 
        
       
         4 
        
       
         − 
        
       
         3 
        
       
         ) 
        
       
         = 
        
       
         0 
        
       
         , 
        
        
        
          x 
         
        
          1 
         
        
       
         ( 
        
       
         1 
        
       
         − 
        
       
         0 
        
       
         ) 
        
       
         = 
        
       
         1 
        
       
      
        x_2(4-3)=0,x_1(1-0)=1 
       
      
    x2(4−3)=0,x1(1−0)=1
 也许你会问为什么要这么解?
 我们看那个递推方程,我们既然知道 
     
      
       
        
        
          F 
         
        
          4 
         
        
       
         ( 
        
        
        
          x 
         
        
          5 
         
        
       
         ) 
        
       
         = 
        
        
        
          f 
         
        
          4 
         
        
       
         ( 
        
        
        
          x 
         
        
          4 
         
        
       
         ) 
        
       
         + 
        
        
        
          F 
         
        
          3 
         
        
       
         ( 
        
       
         x 
        
       
         − 
        
        
        
          x 
         
        
          4 
         
        
       
         ) 
        
       
      
        F_4(x_5)=f_4(x_4)+F_3(x-x_4) 
       
      
    F4(x5)=f4(x4)+F3(x−x4)。然而我们知道了在最大收益时,分配给第4个项目1元钱,这个可以通过代码可以实现。
则 F 3 ( 4 ) F_3(4) F3(4),这个通过查表即可得到41,此时分配给它的钱就是3。同样的也可以逆推出 F 2 F_2 F2和 F 1 F_1 F1中的 x 2 和 x 1 x_2和x_1 x2和x1。就是通过前k-1个项目的最大收益+用剩下钱分配给第k个项目的收益。然而前 k − 1 k-1 k−1个项目的最大收益是保存在了我们的备忘录中,所以这个值不仅可以查到,而且它只计算了一次。没有重复计算。使得这个唯一确定的值+ f 4 ( x 4 ) f_4(x_4) f4(x4)值就是最大收益。
因此我们抛去 f 4 ( x 4 ) f_4(x_4) f4(x4)的值,也就是前k个项目的最大收益 F 3 ( x − x 4 ) F_3(x-x_4) F3(x−x4)。
因此我们可以通过查表得到 x 3 ( x − x 4 ) x_3(x-x_4) x3(x−x4)。故这样计算是合理的
#include<bits/stdc++.h>
using namespace std;
#define MAX_N 4 //最大投资项目数目
#define MAX_M 5 //最大投资钱数(万元)
//f[i][j]的意义:第 i(从 1 开始)个项目投资 j 万元的收益
int f[MAX_N+1][MAX_M+1] = {
    {0,0,0,0,0,0},
    {0,11,12,13,14,15},
    {0,0,5,10,15,20},
    {0,2,10,30,32,40},
    {0,20,21,22,23,24}
}; 
void printNum(int num[MAX_N+1][MAX_M+1]){
    for(int i=0;i<=MAX_M;i++)
    {
        for(int j=0;j<=MAX_N;j++)
        {
            cout << num[j][i] << " ";
        }
        cout << endl;
    }
    return;
}
int main()
{
    int s[MAX_N+1][MAX_M+1] = {0};//s数组用于记录最后一个项目分配的钱
    int F[MAX_N+1][MAX_M+1] = {0};
    for(int i=0;i<=MAX_M;i++){
        F[1][i] = f[1][i];
        s[1][i] = i;
    }
    
    for(int i=2;i<=MAX_N;i++)
    {
        for(int j=0;j<=MAX_M;j++)
        {
            int max = F[i-1][j];
            int cnt = 0;
            for(int k=0;k<=j;k++)
            {
                int num = f[i][k]+F[i-1][j-k];
                if(num>=max)
                {
                    max = num;
                    cnt = k;
                }
            }
            F[i][j] = max;
            s[i][j] = cnt;
        }
    }
    
    printNum(f);
    cout << endl;
    printNum(s);
    cout << endl;
    printNum(F);
    cout << endl;
    int res = s[MAX_N][MAX_M];
    int pro = MAX_N;
    int m = MAX_M;
    while(pro>0)
    {
        cout << "第" << pro << "个项目的钱数为:" << res << endl;;
        pro-=1;
        m-=res;
        res = s[pro][m];
    }
    return 0;
}


![[C++初阶]string类](https://img-blog.csdnimg.cn/direct/582820dee0604ea2ad7e29c78ecc2e20.png)
















