本次通過兩個簡單的演算法題來進一步練習和理解動態規劃,廢話不多說,來上題吧。
給出乙個陣列,如[6,1,1,9,3]在裡面取任意個數,要求所取得數的位置不能相鄰,比如取了第乙個數就不能取第二個數,但是可以取第三第四個數,求取出數之和的最大值。
下面來讓我們分析一下這個題,我們可以分解成求每一位的最優解,從前往後查,如果要求第n個數的最優解,那麼只能有兩種情況:
第一種情況是 取第n個數和第n+2個數的最優解
第二種情況是 取第n+1個數的最優解
因此fib( n ) = max ( arr[n] + fib(n-2) , fib(n-1) ),下面我們用遞迴來解決一下這個問題:
遞迴
static
void
main()
; console.
writeline
(max_sum(0
, arr));
console.
read()
;}static
intmax_sum
(int index,
int[
] arr)
自頂而下static
void
main()
; dictionary<
int,
int> index_max = new dictionary<
int,
int>()
; console.
writeline
(max_sum(0
, arr, index_max));
console.
read()
;}static
intmax_sum
(int index,
int[
] arr, dictionary<
int,
int> index_max)
if(index_max.
containskey
(index +1)
) b = index_max[index +1]
;else
return a > b ? a : b;
}
自底而上static
void
main()
;int
opt = new int
[arr.length]
; opt[0]
= arr[0]
;if(arr[1]
> opt[0]
) opt[1]
= arr[1]
;else
opt[1]
= opt[0]
;for
(int i =
2; i < arr.length; i++
) opt[i]
= arr[i]
+ opt[i -2]
> opt[i -1]
? arr[i]
+ opt[i -2]
: opt[i -1]
; console.
writeline
(opt[arr.length -1]
);console.
read()
;}
這個題我在leetcode上練習時遇到的,雖然不難,但是容易陷入思維誤區。
陣列的每個索引做為乙個階梯,第 i個階梯對應著乙個非負數的體力花費值 cost[i](索引從0開始)。每當你爬上乙個階梯你都要花費對應的體力花費值,然後你可以選擇繼續爬乙個階梯或者爬兩個階梯。您需要找到達到樓層頂部的最低花費。在開始時,你可以選擇從索引為 0 或 1 的元素作為初始階梯。
示例 1:
輸入: cost = [10, 15, 20]
輸出: 15
解釋: 最低花費是從cost[1]開始,然後走兩步即可到階梯頂,一共花費15。
示例 2:
輸入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
輸出: 6
解釋: 最低花費方式是從cost[0]開始,逐個經過那些1,跳過cost[3],一共花費6。
注意:cost 的長度將會在 [2, 1000]。
每乙個 cost[i] 將會是乙個integer型別,範圍為 [0, 999]。
這個題是不是和上一題很像?
上乙個題是fib(n)=max(arr[n]+fib(n-2),fib(n-1))求的是最大值,這個題求得是最小值是不是應該是fib(n)=min(arr[n]+fib(n-2),fib(n-1))?
這和我一開始想的一樣的,但實際上這樣是不對的,如果按照這個思路來寫只會輸出最初的最小值,你可以自行寫一下看看。
這個題實際上是fib(n)=min(fib(n-1),fib(n-2))+arr[n]
因為最後乙個台階是必要走的,可以這樣理解,如果只有乙個台階,那這個台階是必須要走的。
static
void
main()
;int
opt = new int
[cost.length+1]
; opt[0]
=0; opt[1]
= cost[0]
;for
(int i =
1; i < cost.length; i++
) opt[i +1]
=(opt[i]
< opt[i -1]
? opt[i]
: opt[i -1]
)+ cost[i]
; console.
writeline
(opt[cost.length]
< opt[cost.length -1]
? opt[cost.length]
: opt[cost.length -1]
);console.
read()
;}
動態規劃(二)
本節實現乙個動態規劃問題實現。具體問題見上一節 的第三個栗子。這裡再次簡述 在乙個時刻系統可以觀察到的有兩個量 剩餘資料報數量m以及通道狀態h。因此我們將二者聯合組成系統狀態 m,h 那麼在每乙個時隙系統總共有2 m 1 個狀態。每乙個狀態可能跳轉到下乙個時隙的某乙個或者一些狀態。跳轉判斷條件有 在...
動態規劃(二)
之前的兩個問題都是用動態規劃方法解決的,那麼什麼情況下需要使用動態規劃呢?適應動態規劃方法求解的最優化問題應該具備的兩個要素 最優子結構和子問題重疊。用動態規劃方法求解最優化問題的第一步就是刻畫最優解的結構。如果乙個問題的最優解包含其子問題的最優解,就稱此問題具有最優子結構性質。使用動態規劃方法時,...
動態規劃(二)
矩陣鏈乘法問題 給定n個矩陣的鏈,矩陣ai的規模為p i 1 pi 1 i n 求完全括號化方案,使得計算乘積a1a2.an所需標量乘法次數最少。比如矩陣鏈相乘,不同的加括號方式會導致不同的計算代價。假定三個矩陣的規模為10 100 100 5 5 50。若按 a1a2 a3 計算,a1a2需要做1...