动态规划解投资问题

投资问题

m元钱,n项投资,f_i(x):将x元投入项目i中获得的收益,f_i(x)是离散形式的,以表的形式给出,如下表所示,对应5元钱,4项投资,求最大收益对应的投资方案

xf_1(x)f_2(x)f_3(x)f_4(x)
00000
1110220
21251021
313103022
414153223
515204024

动态规划

子问题的界定:
由参数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 \} max0xkx{fk(xk)+Fk1(xxk)}
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=2nx=1m(x+1)=21(n1)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=2nx=1m(x)=21(n1)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];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值