動態規劃--礦工挖礦

動態規劃三要素:邊界、最優子問題、狀態轉移方程;數組

問題描述:現有10個礦工,5個金礦,每一個金礦有對應金子和須要開採的人數,問你最多可以得到多少金子?spa

這是一個典型的動態規劃問題,動態規劃的核心是如何將問題轉換爲重疊的子問題,而且寫出狀態轉移方程。code

首先咱們定義相應的參數:blog

礦工個數:n=10class

金礦個數:w=5遍歷

金子數量:g=[400,500,200,300,350]im

須要人數:p=[5,5,3,4,4]margin

p[i]表明挖了第i個金礦所需人數,g[i]表明挖了第 i個金礦獲得的金子數。令F(n,w)表示n我的挖w個金礦可以獲得的最大金子數。img

當n<p[i]時,也就是說挖第i個金礦的人數不夠,那麼此時能夠得到的最大金子數就是挖第i-1個金礦時的金子:di

F(n,w)=F(n,w-1)

那麼咱們當n>p[i]時,有如下方程:

F(n,w)=max(F(n,w-1),F(n-p[i],w-1)+g[i])

 

表示n我的挖w個金礦可以獲得的最大金子數=最大值(n我的挖w-1個金礦,((n-p[i])我的挖w-1個金礦)+g[i]))

最終代碼:

n=10
w=5
g=[400,500,200,300,350]
p=[5,5,3,4,3]
def goldMining(n,w,g,p):
    #初始化數組,用於存儲信息,注意爲了更好計算,共有11列,第一列做爲輔助位
    dp = [[0 for _ in range(n+1)] for _ in range(w)]
    #邊界就是10我的只挖第1個金礦
    #[0, 0, 0, 0, 0, 400, 400, 400, 400, 400, 400]
    for i in range(1,n+1):
        if i<p[0]:
            dp[0][i]=0
        else:
            dp[0][i]=g[0]
    #依次遍歷金礦,人數
    for i in range(1,w):
        for j in range(1,n+1):
            #若是當前人數小於挖這座金礦的人數
            if j<p[i]:
                #則當前最大金礦就是挖前一個金礦的相應人數的值
                dp[i][j]=dp[i-1][j]
            else:
                #不然就用以下公式計算
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-p[i]]+g[i])
    return dp

dp=goldMining(n,w,g,p)
for i in range(len(dp)):
    print(dp[i])

最終結果:

 

能夠看到,咱們最終能夠得到的最大金子數是900,也就是挖第一個和第二個金礦。 

相關文章
相關標籤/搜索