基本原理
類似於遞迴解題,把問題丟給上一層來解決,找出狀態轉換方程即可。當然關鍵問題是如何定義遞迴陣列與找出狀態轉換方程。
hello world
走樓梯:有n階樓梯,每次能走一步或兩步,請問有多少種走法。
設f(n)是n階樓梯不同的走法。則轉移到此狀態的方法有兩種,從n-1階樓梯走一步上來,或者從n-2階樓梯走兩步上來。此時求解f(n)的任務只需扔給f(n-1)和f(n-2)即可,再定好初始值:f(1)=1,f(2)=2;
f(n)=f(1)+f(2)即可求解。
具體實現中應該維護乙個 陣列,減少重複運算。
max sum(hdoj1003)
題目是給出乙個自然數串,求最長子串,使之和最大。
這裡建立狀態陣列時有些許不同,不能設f(n)是前n個數字構成數字串的max sum,這樣雖然最後求解省事(就是f(n)),但是這樣的話狀態轉移方程就不好寫了。這種假設下,f(n)和前面f(i)關係比較複雜,不能簡單地通過num[i]轉換。
而如果將f(n)設為以n為結尾或者開始的子串的最大值,就要好一點。為什麼呢?我們從最簡單地方法來看,暴力搜尋:
for
(int i=
1; i<=n; i++
)for
(int j=i; j<=n; j++
)}
這裡start和stop的值都是變化的,不像走樓梯問題那樣起點是固定的,只有乙個值在變化。這樣設f(n)是以num[n]為結尾的子串的最大值,便固定了結尾,這樣與f(n-1)的關係就是:f(n)=max(num[n], num[n]+f(n-1)) (f[1]=num[1])即如果前面的最大值都是負數,也沒必要還要前面的子串了。
同理,設f(n)是以num[n]為結尾的子串的最大值,則f(n) = max(num[n],num[n]+f(n+1))
**實現:
#include
using namespace std;
intmain()
, f[
100001]=
, s[
100001]=
; cin>>n;
for(
int ii=
1; ii<=n; ii++
)else
}int max =1;
for(
int i=
2; i<=nn; i++)if
(f[i]
> f[max]
) max = i;
cout<<
"case "
<":"
" "<<<
" "
}}
動態規劃初步
動態規劃的實質是通過多階段決策過程解決最優化問題,將每個問題分為若干個相互聯絡的階段,在它的每一階段都需要做出決策,這就是動態規劃與貪心演算法的區別,貪心演算法是以一種貪心規則進行最優運算,但往往得到的結果並不是問題的最優解,而動態規劃則不同,動態規劃是每一步都有乙個決策,保證了最優解是我們要找的整...
動態規劃初步
動態規劃的核心是狀態和狀態轉移方程。計算狀態轉移方程的方法 1 遞迴計算。用直接遞迴的方法計算狀態轉移方程,效率往往十分低下。其原因是相同的子問題被重複計算了多次。2 遞推計算。遞推的關鍵是邊界和計算順序。3 記憶化搜尋。不必事先確定各狀態的計算順序,但需要記錄每個狀態 是否已經計算過 動態規劃基礎...
動態規劃初步探索
下面用乙個很簡單的例子來具體說明一下dp問題的解題過程。題目如下 描述在乙個星期三的早上,某同學想用扔硬幣的方式來決定是否要去上演算法課。他扔 n 次硬幣,如果當中有連續 m 次以上 含 m 次 的結果都是正面,那麼他就去上課,否則就接著睡覺。假設每次扔硬幣扔出的正反兩面的概率都是 0.5。輸入 輸...