(學習7)動態規划——投資問題


動態規划是一種算法設計技術。

特點 1:由交疊的子問題構成;特點2:滿足最優法;

投資問題:

有n個項目,有m元可以去投資,列出每個項目的投資與收益情況,問該如何分配這m元?

投入(m) 項目1(f1/x1) 項目2(f2/x2) 項目3(f3/x3) 項目4(f4/x4)
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

這個問題滿足的約束條件為:x1+x2+x3+x4=m

目標函數:max{f1(x1)+f2(x2)+f3(x3)+f4(x4)}

一個推論:一個最優策略的任何子序列一定相對於該子序列開始與結束的最優決策序列。

偽代碼:

memset(Fx,0,sizeof(Fx)); //初始化都為0
for (int k=1;k<=n;k++)  //前k個項目
  for(int x=1;x<=m;x++) //投入x元
     for(int z=0;z<=x;z++)  //投入項目k為z元
        Fx[k][x]=max(Fx[k][x],Fx[k-1][x-z]+f[k][z]);

解析(第一次純手工dp后,用電子稿寫出來......):

n=1
F[1][0]=0  F[1][1]=11    MAX(F[1][1])=11
F[1][0]=0  F[1][1]=11 F[1][2]=12   MAX(F[1][2])=12
F[1][0]=0  F[1][1]=11 F[1][2]=12 F[1][3]=13  MAX(F[1][3])=13
F[1][0]=0  F[1][1]=11 F[1][2]=12 F[1][3]=13  F[1][4]=14  MAX(F[1][4])=14
F[1][0]=0  F[1][1]=11 F[1][2]=12 F[1][3]=13  F[1][4]=14  F[1][5]=15  MAX(F[1][5])=15
n=2
F[2][0]=11  F[2][1]=0    MAX(F[2][1])=11
F[2][0]=12  F[2][1]=11  F[2][2]=5   MAX(F[2][2])=12
F[2][0]=13   F[2][1]=12  F[2][2]=16  F[2][3]=10  MAX(F[2][3])=16
F[2][0]=14   F[2][1]=13  F[2][2]=17  F[2][3]=21  F[2][4]=15  MAX(F[2][4])=21
F[2][0]=15  F[2][1]=14  F[2][2]=18 F[2][3]=22   F[2][4]=26  F[2][5]=20  MAX(F[2][5])=26

n=3
F[3][0]=11  F[3][1]=2    MAX(F[3][1])=11
F[3][0]=12  F[3][1]=13  F[3][2]=10   MAX(F[3][2])=13
F[3][0]=16   F[3][1]=14  F[3][2]=21  F[3][3]=30  MAX(F[3][3])=30
F[3][0]=21   F[3][1]=18  F[3][2]=22  F[3][3]=41  F[3][4]=32  MAX(F[3][4])=41
F[3][0]=26  F[3][1]=23  F[3][2]=26 F[3][3]=42   F[3][4]=43  F[3][5]=40  MAX(F[3][5])=43


n=4
F[4][0]=11  F[4][1]=20    MAX(F[4][1])=20
F[4][0]=13  F[4][1]=31  F[4][2]=34   MAX(F[4][2])=34
F[4][0]=30   F[4][1]=33  F[4][2]=32  F[4][3]=22  MAX(F[4][3])=33
F[4][0]=41   F[4][1]=50  F[4][2]=35  F[4][3]=34  F[4][4]=23  MAX(F[4][4])=50
F[4][0]=43  F[4][1]=61  F[4][2]=51 F[4][3]=35   F[4][4]=34  F[4][5]=24  MAX(F[4][5])=61

最后輸出的MAX(F[4][5])=61即為最大收益

 

源代碼

//
//  main.cpp
//  作業7
//
//  Created by yizhihenpidehou on 2020/4/7.
//  Copyright © 2020 yizhihenpidehou. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxen=200;
int Fk[maxen][maxen]={0};//存放第k個項目投資x元可以獲得的最大收益
int fk[maxen][maxen]={0};//存放第k個項目x元可以獲得的收益
int dp(int n,int m){
    for(int k=1;k<=n;k++){//前k個項目
        for(int x=1;x<=m;x++){//前K個項目共投資多少錢
            for(int z=0;z<=x;z++){//給第K個項目分配多少錢
                Fk[k][x]=max(Fk[k][x],fk[k][z]+Fk[k-1][x-z]);
                //計算錢該怎么分配給第k個項目與前k-1個項目收益最大
            }
        }
    }
    return Fk[n][m]; //返回收益最大的情況(因為每次Fk[k][x]都是存最大收益)
}
int main(int argc, const char * argv[]) {
    int n=4,m=5;//有4個項目,共有5萬元
    memset(Fk,0,sizeof(Fk));
    memset(fk,0,sizeof(fk));
    fk[1][0]=0;fk[1][1]=11;fk[1][2]=12;fk[1][3]=13;fk[1][4]=14;fk[1][5]=15;
    fk[2][0]=0;fk[2][1]=0;fk[2][2]=5;fk[2][3]=10;fk[2][4]=15;fk[2][5]=20;
    fk[3][0]=0;fk[3][1]=2;fk[3][2]=10;fk[3][3]=30;fk[3][4]=32;fk[3][5]=40;
    fk[4][0]=0;fk[4][1]=20;fk[4][2]=21;fk[4][3]=22;fk[4][4]=23;fk[4][5]=24;
    int maxx=dp(n,m);
    printf("maxx:%d\n",maxx);
    return 0;
}
View Code

時間復雜度:O(nm²)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM