投资问题
m元钱,n项投资,f_i(x):将x元投入项目i中获得的收益,f_i(x)是离散形式的,以表的形式给出,如下表所示,对应5元钱,4项投资,求最大收益对应的投资方案
x | f_1(x) | f_2(x) | f_3(x) | f_4(x) |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 11 | 0 | 2 | 20 |
2 | 12 | 5 | 10 | 21 |
3 | 13 | 10 | 30 | 22 |
4 | 14 | 15 | 32 | 23 |
5 | 15 | 20 | 40 | 24 |
动态规划
子问题的界定:
由参数k和x确定:对k个项目进行投资,对给定的k,x遍历0到m
原始问题:k=m,x=n
递推方程:
F
k
F_k
Fk(x)表示x元钱投给前k个项目所能获得的最大效益
G
k
G_k
Gk(x)表示对应
F
k
F_k
Fk(x)的投资方案投给第k个项目的钱
F
k
F_k
Fk(x)=
max
0
≤
x
k
≤
x
{
f
k
(
x
k
)
+
F
k
−
1
(
x
−
x
k
)
}
\max_{0\leq x_{k}\leq x }\left \{ f_{k}(x_{k})+F_{k-1} (x-x_{k})\right \}
max0≤xk≤x{fk(xk)+Fk−1(x−xk)}
F
1
F_1
F1(0)=0,
F
2
F_2
F2(0)=0,
F
3
F_3
F3(0)=0,
F
4
F_4
F4(0)=0
F
1
F_1
F1(1)=11,
F
1
F_1
F1(2)=12,
F
1
F_1
F1(3)=13,
F
1
F_1
F1(4)=14,
F
1
F_1
F1(5)=15
k=2,x遍历1到5
F
2
F_2
F2(1)=max{
f
2
f_2
f2(0)+
F
1
F_1
F1(1-0),
f
2
f_2
f2(1)+
F
1
F_1
F1(1-1)}=max{11,0}=11
以此类推,求出
F
n
(
m
)
F_n(m)
Fn(m)
复杂度分析:
计算
F
k
F_k
Fk(x)时,
x
k
x_k
xk有x+1种可能,需要x+1次加法,x次比较
加法次数:
∑
k
=
2
n
∑
x
=
1
m
(
x
+
1
)
=
1
2
(
n
−
1
)
m
(
m
+
3
)
\sum_{k=2}^{n}\sum_{x=1}^{m}(x+1)=\frac{1}{2}(n-1)m(m+3)
∑k=2n∑x=1m(x+1)=21(n−1)m(m+3)
比较次数:
∑
k
=
2
n
∑
x
=
1
m
(
x
)
=
1
2
(
n
−
1
)
m
(
m
+
1
)
\sum_{k=2}^{n}\sum_{x=1}^{m}(x)=\frac{1}{2}(n-1)m(m+1)
∑k=2n∑x=1m(x)=21(n−1)m(m+1)
时间复杂度O(n
m
2
m^2
m2)
代码实现
#include "all_function.h"
using namespace std;
int invest(){
int n,m;
cout<<"please input all money:";
cin>>m;
cout<<"please input the number of project:";
cin>>n;
vector<vector<int> > data(m+1,vector<int>(n));
vector<vector<int> > planning_profit(m+1,vector<int>(n,0));
vector<vector<int> > distribution(m+1,vector<int>(n,0));
for(int i=0;i<n;++i){
cout<<"the profit data for project"<<i<<endl;
for(int j=0;j<=m;++j){
int profit;
cout<<"please input the profit when you give "<<j<<" yuan to project "<<i<<" :";
cin>>profit;
data[j][i]=profit;
}
}
for(int i=0;i<m+1;++i){//投第一个项目i元钱获得的收益
planning_profit[i][0]=data[i][0];
distribution[i][0]=i;
}
for(int i=1;i<n;++i){//投资前i+1个项目,从第2个项目计
for(int j=0;j<m+1;++j){//投入j元钱,从0至m
int max_profit=data[0][i]+planning_profit[j][i-1];
distribution[j][i]=0;
for(int k=1;k<j+1;++k){//投给第i+1个项目的钱,从1元计
int profit=data[k][i]+planning_profit[j-k][i-1];
if(profit>max_profit){
max_profit=profit;
distribution[j][i]=k;
}
}
planning_profit[j][i]=max_profit;
}
}
for(int i=0;i<m+1;++i)
for(int j=0;j<n;++j)
cout<<planning_profit[i][j]<<" ";
cout<<endl;
cout<<endl;
for(int i=0;i<m+1;++i)
for(int j=0;j<n;++j)
cout<<distribution[i][j]<<" ";
cout<<"max profit:"<<planning_profit[m][n-1]<<endl;
cout<<"best invest plan :"<<endl;
int left_money=m;
int last_project=n-1;
cout<<"project "<<last_project+1<<" :"<<distribution[left_money][last_project]<<endl;
while(1){
left_money=left_money-distribution[left_money][last_project];
--last_project;
if(last_project<0)
break;
cout<<"project "<<last_project+1<<" :"<<distribution[left_money][last_project]<<endl;
}
return planning_profit[m][n-1];
}