動態規划三要素:邊界、最優子問題、狀態轉移方程;
問題描述:現有10個礦工,5個金礦,每個金礦有對應金子和需要開采的人數,問你最多能夠獲得多少金子?

這是一個典型的動態規划問題,動態規划的核心是如何將問題轉換為重疊的子問題,並且寫出狀態轉移方程。
首先我們定義相應的參數:
礦工個數:n=10
金礦個數:w=5
金子數量:g=[400,500,200,300,350]
需要人數:p=[5,5,3,4,4]
p[i]代表挖了第i個金礦所需人數,g[i]代表挖了第 i個金礦得到的金子數。令F(n,w)表示n個人挖w個金礦能夠得到的最大金子數。
當n<p[i]時,也就是說挖第i個金礦的人數不夠,那么此時可以獲得的最大金子數就是挖第i-1個金礦時的金子:
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,也就是挖第一個和第二個金礦。
