投资问题
题目描述
-
设有 m 元钱,n项投资,函数f i ( x )表示将 x 元投入第 i 项项目所产生的效益,i= 1,2,…,n,问:如何分配这 m 元钱,使得投资的总收益最高?
-
动态规划问题需要将问题划分为子问题,然后求出子问题的最优解,然后利用子问题的解逐级来求出最终问题的解
-
求解思路:对于这道题我们需要设置两个参数 (1)将项目划分为n各阶段,比如先对第一个项目考虑,然后是两个项目…(2)每个项目下还存在另一个可变参数:X->即投资的钱数
-
注意!!!:作为约束条件的参数不能讨论子问题,也就是投资的钱数不能作为第一个参数来讨论子问题,因为投资的钱数是投资项目的约束条件
-
(2)首先介绍三个函数:
1)效益函数f_k(x):
x | f_1(x) | f_2(x) | f_3(x) | f_4(x) | x | f_1(x) | f_2(x) | f_3(x) | f_4(x) |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 3 | 13 | 10 | 30 | 22 |
1 | 11 | 0 | 2 | 20 | 4 | 14 | 15 | 32 | 23 |
2 | 12 | 5 | 10 | 21 | 5 | 15 | 20 | 40 | 24 |
2)F_k(x)函数:表示x万元投给前k个项目的最大收益
3)x_*k(x)*函数:表示F_k(x)函数取得最大值时要分配给第K个项目对应的钱数,用于解的回溯
-
最简单的子问题当然是只投给第一个项目了,此时投资的金额数x=1,2,3,4,5,根据效益函数表格可以很轻松的得到如下数据
F_1(1) =f_1(1)=11,F_1(2) =f_1(2)=12,F_1(3) =f_1(3)=13,F_1(4) =f_1(4)=14,F_1(5) =f_1(5)=15,
-
再讲解一下第二步,F_2(x),x的取值为1,2,3,4,5 比如F_2(1)->将一万元分给前两个项目,那么就有两种情况
(1)第一个项目一万元,第二个项目0元
(2)第一个项目0元,第二个项目一万元
*所以F_2(1)=max{ f_ 2(0) + F_1(1) ,f_2(1)+F_1(0) },从(1)(2)中选择出最大的值就代表了F_2(1)的最大值 *
-
同理可以求出F_*2(2),F_*2(3),*F_*2(3),*F_*2(4),*F_*2(5),这里就不给大家一一展示了 ,在程序中只需要用三个循环就可以实现
-
备忘录:用来存放我们求出的最大值,用来求出问题的解,用一个二维数组就可以实现
x | F_1(x) x_1(x)) | F_2(x) x_2(x)) | F_3(x) x_3(x)) | F_4(x) x_4(x)) |
---|---|---|---|---|
1 | 11 0 | 20 1 | ||
2 | 12 2 | 12 0 | 3 1 | 31 1 |
3 | 13 3 | 16 2 | 30 3 | 33 1 |
4 | 14 4 | 21 3 | 50 1 | |
5 | 15 5 | 26 4 | 43 4 |
-
解的追溯:从表中可知最大的收益是61万元,那么怎么追溯解呢?首先查到x_4(5)的值为1,说明收益最大时第四个项目分到的资金是1万元,那么剩下的4万元分给了前三个项目,所以我们查找到了x_3(4)=3,说明第三个项目分到了3万元,那么前两个小组分到的是1万元,所以x_2(1)=0,说明这一万元全部分给了第一项,第二个项目分到0元,分析到这里这个问题的最优解便为:
分配方案:x_1=1,x_2=0,x_3=3,x_4=1
最大收益:F_4(5)=61
-
c++语言实现代码
//投资问题,m元钱,n项投资,f\[i]\[x]表示将x元投入第i项项目所产生的收益,问如何分配这m元钱使得投资的收益最高? //输入:m n f\[n]\[m](根据课本的数据手动给定) //输出:最高收益以及如何分配的方法 #include <iostream> #include <algorithm> using namespace std; int main() { int m = 5; int n = 4; int f[5][6] = {0}; f[1][1] = 11, f[1][2] = 12, f[1][3] = 13, f[1][4] = 14, f[1][5] = 15; f[2][1] = 0, f[2][2] = 5, f[2][3] = 10, f[2][4] = 15, f[2][5] = 20; f[3][1] = 2, f[3][2] = 10, f[3][3] = 30, f[3][4] = 32, f[3][5] = 40; f[4][1] = 20, f[4][2] = 21, f[4][3] = 22, f[4][4] = 23, f[4][5] = 24; int F[5][6] = {0}; //F[k][x] 表示 将x万元钱分配到前k个项目取得的最大收益 int x[5][6] = {0}; //用来储存当F[k][x]取得最大值时, 第k个项目被投资了多少万元钱 for (int i = 1; i <= 5; i) { F[1][i] = f[1][i]; //当把i万元前全部分配给第一个项目的时候,取得最大的收益就是对应的收益函数f x[1][i] = i; //因为只有一个项目,全部投! } for (int i = 2; i <= 4; i) //枚举分配前两个项目、前三个,前四个 { for (int j = 1; j <= 5; j) //枚举投资1万元,2万云…… { int _max = 0; for (int k = 0; k <= j; k) { if (f[i][k] + F[i - 1][j - k] > _max) { _max = f[i][k] + F[i - 1][j - k]; //更新当前情况的最大收益 x[i][j] = k; //记录下当用j万元钱给前i个项目投资时,第i个项目被投资的钱数k } } F[i][j] = _max; } } cout << "最大收益额为" << F[4][5] << endl; int money = 5; for (int i = 4; i >= 1; i--) //解的追溯 { cout << "第" << i << "个项目投资" << x[i][money] << "元" << endl; money -= x[i][money]; } return 0; }