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


問題:
有一個國家發現了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                                  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

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



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