問題:
有一個國家發現了5座金礦,每座金礦的黃金儲量不一樣,須要參與挖掘的工人數也不一樣。參與挖礦工人的總數是10人。
每座金礦要麼全挖,要麼不挖,不能派出一半人挖取一半金礦。要求用程序求解出,要想獲得儘量多的黃金,應該選擇挖取哪幾座金礦?
動態規劃有三個核心元素:
最優子結構、
邊界、
狀態轉移 方程式。
該問題中要求10個工人5個金礦,挖最多黃金的選擇。所以最優子結構有兩種狀況:
- 10個工人4個金礦時,挖出最多黃金的選擇。
- 4金礦,工人數:10-最後一個金礦須要的人數。
咱們把金礦數量設爲n,工人數設爲m,金礦的黃金量設爲g[],金礦的用工量設爲數組p[],該問題中,各數據以下所示:
n=5, m=10, g = [400,500,200,300,350], p = [5,5,3,4,3]
那麼5座金礦和4作金礦的最優選擇之間存在這樣的關係:F(5,10) = MAX(F(4,10),F(4,10-P[4]+G[4]))
如今給出邊界,也就是金礦數量n爲1時:
當n=1,m>=p[0]時,F(n,m) = g[0];
當n=1,m<p[0]時,F(n,m) = 0;
使用格子推導出全部的狀況:
對某一狀況進行分析,如F(3,8),其結果就是MAX(F(2,8),F(2,8-P[3]) + G[3]) = 700
狀態轉移方程:
F(n,m) = 0 (n<=1,m<p[0]);
F(n,m) = g[0](n==1,m>=p[0]);
F(n,m) = F(n-1,m)(n>1,m<p[n-1]);
F(n,m) = max(F(n-1,m), F(n-1,m-p[n-1])+g[n-1])(n>1,m>=p[n-1]);
js代碼以下:
//n:金礦數量 m:工人數量 g:得到金額數組 p:須要工人數組
function getMostGold(n,m,g,p){
var preResults = [];
var results = [];
for(var i = 0; i <= m; i++){
if(i < p[0]){
preResults[i] = 0;
}else{
preResults[i] = g[0];
}
}
for(var t = 0;t < preResults.length; t++){
results[t] = preResults[t];
}
if(n == 1){
return results[m];
}
for(var i = 1;i < n; i++){
for(var j = 0; j <= m; j++){
if(j < p[i]){
results[j] = preResults[j];
}else{
//實際上就是管無論最後一個金礦的問題
results[j] = Math.max(preResults[j],preResults[j-p[i]] + g[i]);
}
}
console.log(results);
for(var t = 0;t < preResults.length; t++){
preResults[t] = results[t];
}
}
return results[m];
}
var g = [400,500,200,300,350];
var p = [5,5,3,4,3];
console.log(getMostGold(5,10,g,p));
其中須要注意的是,js中數組拷貝須要使用深拷貝,使用淺拷貝(preResults = results)會產生數據問題。
原文連接以下:http://www.sohu.com/a/153858619_466939