投資問題的描述: fi(x)表示的是 把 x 元錢投資到第 i 個項目 所獲得的收益。課堂上老師說,約束條件必須滿足 投資的錢數 等於總共的錢數
舉例說明,更容易理解: 在這個表格中, 比如 坐標 (1,0)對應的值為11,這個含義就是說 把 1 萬元投資到項目1中,獲得的收益是 11萬元。坐標 (3,4)的值為 22, 這個含義就是說 把 3 萬元 投資到 項目 4 中,獲得的收益是 22萬元。
子問題的界定:
k代表的含義是 ,考慮到第幾個項目
x代表的含義是: 你投資的錢數不超過 x
所以,這里的 k 和 x 是兩個性質不同的參數。
我們之前學的矩陣鏈相乘, 問題中的 i ,j 是矩陣的下標。是同樣類型的參數。
再討論計算順序, 先定下 所要投資的項目,是前 k 個,從1,2,3......k
當k 的值確定以后,再讓 x 變化。比如,當k的值為5時,我們考慮 x 為1,2,3,4....m 時,獲得的收益。
優化函數的遞推方程: Fk(x)表示的意思是 把 x 元 投資給 前 k 個項目 獲得的最大收益。
x的范圍(投資的總的錢數) 是0 到 x
k 的范圍是 1 到 n (總共有 n 個項目)
那么 Fk(x) 的值應該是 對 第k個項目投資 了 xk 元 后的收益 + 把剩下的錢(x-xk)投給 前 k-1個項目的總的收益 Fk-1(x-xk)
那么,這個 xk的值 可以從 0 到 x,就是說,可以一分錢也不投資給 第k個項目,也可以把所有錢都投資給 這個項目,所以,這里要遍歷 x+1次 才可以獲得收益的最大值。
下面舉例說明,當 k=1 時, 就是說 考慮前面 第一個 項目。只投資第一個項目。
把 0元投資給第一個項目,收益為0元,
把 1 元投資給第一個項目,收益為 11元
把 2 元投資給第一個項目,收益為 12 元,以此類推
舉例說明,當K=2 時, 我們考慮把 錢投資給 前 2 個項目。
K確定以后,我們就要來遍歷 x ,x是投資的總的錢數,范圍是 從 0 到 5.
當 x= 5時,我們分析情況:
方案有 :(0,5),(5,0),(1,4),(4,1),(2,3),(3,2)
F2( x=5)=max{ f1(0)+f2(5) , f1(5)+f2(0) , f1(1)+f2(4) , f1(4)+f2(1) , f1(2)+f2(3) , f1(3)+f2(2) }
max { 0 +20 , 15+0 , 11 +15 , 14 +0 ,12 + 10 , 13+5 } ,所以,此時最大的收益是 26 萬元。
備忘錄 和解:
F1(x )就是我們剛剛提到的, 把 x萬元投在到 前 k 個項目中,這里 k=1
那么 , x 1(x) 是什么意思呢,這是標記函數, 表示的意思是, 你得到當前的最大收益時,你給了最后一個項目多少錢
比如 ,我們剛剛算的 F 2(5) ,我們把5萬元投資到前 2 個項目中, 當獲得最大收益 26 萬元時, 我 們給第二個項目
投資的是4萬元。 上面已經說的很清楚了。
那我們來舉個不同的例子分析一下。
比如我要追蹤 我投資 4萬元給 這四個項目獲得的最大收益,顯然是 50萬元。
此時,給第四個項目的投資是1 萬元, x 4( 4)=1, 也就是說, x4=1,d第四個項目投資 1萬元
x3(3)= 3, 也就是說,我們把剩余的3 萬元全部投資給了 第三個項目
剩下的錢為 0 ,無法投資
時間復雜度分析:
有兩種分析方法,
小結:
代碼實現:

#include<iostream> #include<vector> using namespace std; int main() { int m, n;//m元錢,n項投資 int i, j;//循環輔助變量 int tmp_m,tmp_F=0;//tem_m代表給第i個項目投入的錢數 0<=tmp<=j;tmp_F代表一次循環中的錢數 cin >> m >> n; vector<vector<int>> f(n, vector<int>(m + 1));//f[i][x], 0<i<=n,0<=x<=m; vector<vector<int>> F(n, vector<int>(m + 1));//F[i][x],將x元錢投入到前i個項目上最大的收益 for (i = 0; i < n; ++i) { f[i][0] = 0;//在第(i+1)個項目上投入0元,收益為0,注意i從0開始 } for (i = 0; i < n; ++i) { for (j = 1; j < m + 1; ++j) {//j從1開始,也就是從f[0][1]開始 cin >> f[i][j]; } } //給F[0][0-m]賦值 for (j = 0; j < m + 1; ++j) { F[0][j] = f[0][j];//第一個項目上投入0-m元錢的最大收益等於f[0][0-m] } for (i = 1; i < n; ++i) {//項目循環,從1開始,也就是從前2個項目開始算,因為第一個項目已經賦值 for (j = 0; j < m + 1; ++j) {//錢數循環 從0開始 for (tmp_m = 0; tmp_m <= j; ++tmp_m) { tmp_F = F[i - 1][j - tmp_m] + f[i][tmp_m]; if (tmp_F > F[i][j]) F[i][j] = tmp_F; } } } cout << "the max profit is : " << F[n - 1][m] << endl; }
實現結果:
控制台輸入說明:
輸入:第一行為總錢數m和總項目數n;接下來為n行輸入,每行m個,代表f[i][x]。
輸出:最大收益。