動態規劃問題----國王和金礦

問題:
有一個國家發現了5座金礦,每座金礦的黃金儲量不一樣,須要參與挖掘的工人數也不一樣。參與挖礦工人的總數是10人。
每座金礦要麼全挖,要麼不挖,不能派出一半人挖取一半金礦。要求用程序求解出,要想獲得儘量多的黃金,應該選擇挖取哪幾座金礦?

動態規劃有三個核心元素: 最優子結構邊界狀態轉移 方程式
該問題中要求10個工人5個金礦,挖最多黃金的選擇。所以最優子結構有兩種狀況:
  1. 10個工人4個金礦時,挖出最多黃金的選擇。
  2. 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                                  
相關文章
相關標籤/搜索