1. 程式人生 > >通過金礦模型介紹動態規劃

通過金礦模型介紹動態規劃

/*
=========程式資訊========
對應題目:01揹包之金礦模型
使用語言:c++
使用編譯器:Visual Studio 2005.NET
使用演算法:動態規劃
演算法執行時間:O(people * n) [people是人數,n是金礦數]
作者:貴州大學05級 劉永輝 
暱稱:SDJL
編寫時間:2008年8月
聯絡QQ:44561907
E-Mail:[email protected]
獲得更多文章請訪問我的部落格:www.cnblogs.com/sdjl
如果發現BUG或有寫得不好的地方請發郵件告訴我:)
轉載請保留此部分資訊:)
*/

#include 
"stdafx.h"
#include 
<iostream>
#include 
<fstream>usingnamespace std;

constint max_n =100;//程式支援的最多金礦數constint max_people =10000;//程式支援的最多人數int n;//金礦數int peopleTotal;//可以用於挖金子的人數int peopleNeed[max_n];//每座金礦需要的人數int gold[max_n];//每座金礦能夠挖出來的金子數int maxGold[max_people][max_n];//maxGold[i][j]儲存了i個人挖前j個金礦能夠得到的最大金子數,等於-1時表示未知

//初始化資料 void init()
{
    ifstream inputFile(
"beibao.in");
    inputFile
>>peopleTotal>>n;
    
for(int i=0; i<n; i++)
        inputFile
>>peopleNeed[i]>>gold[i];
    inputFile.close();
            
    
for(int i=0; i<=peopleTotal; i++)
        
for(int j=0; j<n; j++
)
            maxGold[i][j] 
=-1;//等於-1時表示未知 [對應動態規劃中的“做備忘錄”]        
}

//獲得在僅有people個人和前mineNum個金礦時能夠得到的最大金子數,注意“前多少個”也是從0開始編號的int GetMaxGold(int people, int mineNum)
{
    
//申明返回的最大金子數int retMaxGold;

    
//如果這個問題曾經計算過  [對應動態規劃中的“做備忘錄”]if(maxGold[people][mineNum] !=-1)
    {
        
//獲得儲存起來的值        retMaxGold = maxGold[people][mineNum];
    }
    
elseif(mineNum ==0)//如果僅有一個金礦時 [對應動態規劃中的“邊界”]    {
        
//當給出的人數足夠開採這座金礦if(people >= peopleNeed[mineNum])
        {    
            
//得到的最大值就是這座金礦的金子數            retMaxGold = gold[mineNum];
        }
        
else//否則這唯一的一座金礦也不能開採        {
            
//得到的最大值為0個金子            retMaxGold =0;
        }
    }
    
elseif(people >= peopleNeed[mineNum])//如果給出的人夠開採這座金礦 [對應動態規劃中的“最優子結構”]    {
        
//考慮開採與不開採兩種情況,取最大值        retMaxGold = max(GetMaxGold(people - peopleNeed[mineNum],mineNum -1+ gold[mineNum],
                                        GetMaxGold(people,mineNum 
-1));
    }
    
else//否則給出的人不夠開採這座金礦 [對應動態規劃中的“最優子結構”]    {
        
//僅考慮不開採的情況        retMaxGold  = GetMaxGold(people,mineNum -1);
    }
    
    
//做備忘錄        maxGold[people][mineNum] = retMaxGold;
    
return retMaxGold;
}

int _tmain(int argc, _TCHAR* argv[])
{
    
//初始化資料    init();
    
//輸出給定peopleTotal個人和n個金礦能夠獲得的最大金子數,再次提醒編號從0開始,所以最後一個金礦編號為n-1    cout<<GetMaxGold(peopleTotal,n-1);
    system(
"pause");
    
return0;
}