動態規划是一種算法設計技術。
特點 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; }
時間復雜度:O(nm²)