經典的dp!
有n多情況的整數劃分,下面就幾種這幾天學習的分別說一下:
1. 數n的劃分中,其最大值不能大於k:記其結果為f(n, k),那麼,
狀態轉移方程:當 n == 1 || k == 1 時,f(n, k) == 1, n為1,那麼只能為1; 而k為1,那麼只能劃分成n個1. 當 n < k 時,f(n, k) == f(n, n),因為n的劃分中不可能出現比n大的數,所以可以將最大值從k降到n; 當 n >= k 時,f(n, k) = f(n-k, k) + f(n, k-1), 前半部分是劃分中存在最大值k,所以可以在(n-k)中繼續以最大值為k來劃分,而後半部分則是劃分中最大值不是k,那麼其結果和以(k-1)為最大值的劃分是一樣的。在初始化中可以將f(0, k)初始化為1,及對應f(n, n)可能出現的
情況,這樣那麼最後的程式為:
void dp()
for(int i = 2; i <= 120; i++) }
} !!如果這種情況下求取a[n][k],而 k >= n ,其結果就是n的所有劃分之和。
2. 將n劃分成k個正整數之和的劃分數:當 n < k 時,顯然是不可能的,那麼f(n, k) == 0; 當 k == 1 時,f(n, k) == 1; 當 n >= k 時,f(n, k) = f(n-k, k) + f(n-1, k-1),前半部分對應這k個數中不存在1的情況,那麼我們就可以將劃分中每個數都減去1,剩下的輸仍然是大於0的,等價於將n減去了k,而後半部分這是對應這k個數中存在1的情況,最終程式可以如下:
void dp() }
}!!如果要求可以小於k,那麼就可以將結果從1一直加到k。
3. 將n劃分成若干個奇正整數之和的劃分數:f(n, k) 表示n的劃分中最大值為k的劃分數。當 k == 1 時,其結果只能為n個1,當 k 是偶數時,有f(n, k) == f(n, k-1);當 k > n 時,有f(n, k) == f(n, n),理由同1;當 n >= k 時,有 f(n, k) = f(n, k-1) + f(n-k, k) 《此式中k為奇數,偶數可以對應前面的情況》,前半部分對應n的劃分數中最大值不為k,那麼可以從k-2開始,式中 k-1 的效果也能達到,同時還能在遞推中防止出現下標為負的情況;最終的程式可以如下:
void dp()
for(int i = 1; i <= 100; i++) else }
} }4. 將n劃分成若干不同整數之和的劃分數:f(n, k) 表示n的劃分中最大值為k的劃分數。當 k == 1 時,f(n, k) = 1;當 n < k 時;f(n, k) == f(n, n),理由同1;當 n >= k 時,有 f(n, k) == f(n-k, k-1) + f(n, k-1),前半部分對應的是劃分中存在k,而後一種情況對應n的劃分中不存在k,這兩種情況下都將遞迴條件從k換成 k-1 是因為當前的兩種情況已經將k的所有情形都已考慮,而劃分中k不能重複。所以最終的程式可以為:
void dp() }
}!!小結:這裡只是幾種典型的整數劃分情形,對這幾種整數劃分,找出動態規劃的狀態轉移方程很關鍵,但各種情況下的初始化條件也很important,不然就一直 wa wa wa 。。。
整數劃分問題的遞迴解法
整數劃分問題是演算法中的乙個經典命題之一,有關這個問題的講述在講解到遞迴時基本都將涉及。所謂整數劃分,是指把乙個正整數n寫成如下形式 n m1 m2 mi 其中mi為正整數,並且1 mi n 則為n的乙個劃分。如果中的最大值不超過m,即max m1,m2,mi m,則稱它屬於n的乙個m劃分。這裡我們...
整數劃分問題 經典DP
相關題目1 相關題目2 相關題目3 下面的描述大部分借鑑於 感謝,但是其中有部分錯誤,我會在下面的描述中糾正過來 總的解決方法時截邊法,也就是去討論有1無1的情況和截去他們的情況 記住了.1.若劃分的多個整數可以相同 設dp i j 為將i劃分為不大於j的劃分數 1 當i j 時,i不能劃分為大於i...
經典遞迴問題 整數劃分問題
題目 將乙個正整數n表示成一系列正整數之和,n n1 n2 nk,其中n1 n2 nk 1,k 1 正整數n的乙個這種表示稱為正整數n的乙個劃分。正整數n的不同劃分個數稱為正整數n的劃分數,記做p n 如正整數6有如下11種不同的劃分,所以p 6 11。6 5 1 4 2,4 1 1 3 3,3 2...