DP系列:
https://blog.csdn.net/nameofcsdn/article/details/106417240
動態規劃的核心在於分析最優子結構,其中包含如下內容:
如何描述問題,如何描述子問題,問題的解和子問題的解之間的關係,即遞推式,問題的解空間結構,如何遍歷這個解空間,等等。
問題的描述形式,取決於我們所求的答案的形式和結構.
個人理解主要分三種情形:
(1)完全按照題目所求來描述
(2)基於答案分解,附加特殊規則的精確化描述
(3)自帶空間壓縮的降維描述
對於問題本身的描述很複雜的題目,我們的描述越精確,我們的遞推式也就越簡潔。
例如:
(1)完全按照題目所求來描述
例1:力扣 OJ 1143. 最長公共子序列 https://blog.csdn.net/nameofcsdn/article/details/104091938
f(a,b)表示數組A的前a個數和數組B的前b個數的最長公共子序列
(2)基於答案分解,附加特殊規則的精確化描述
什麼叫基於答案分解呢?
要求前n個數的最長上升子序列,我們可以把答案分解爲n種情況:
以第i個數(i從1到n)爲結尾的最長上升子序列
例2:力扣 OJ 300. 最長上升子序列 https://blog.csdn.net/nameofcsdn/article/details/104086350
給定一個無序的整數數組,找到其中最長上升子序列的長度。
f(i)表示以第i個數結尾的最長上升子序列的長度
f(i-1)表示以第i-1個數結尾的最長上升子序列的長度
所以f(i)=max{f(j) | j<i && num[j]<num[i]}
例3:CSU 1225: ACM小組的隊列(最長上升子序列的個數)https://blog.csdn.net/nameofcsdn/article/details/79747086
這個題目需要把以第i個數結尾的最長上升子序列的長度和數目一起算出來。
PS:完全按照題目所求來描述,求得的值就是答案,
基於答案分解,附加特殊規則的精確化描述,求得值之後,還要在所有值裏面取一個最優解
PS:基於答案分解是根據答案的最後一個值,分解成很多情況,得到的是分解問題,形式和原問題不同
而子問題是形式和原問題相同,但規模比原問題小,是原問題經過分治思想得到的。
(3)自帶空間壓縮的降維描述
首先,什麼是空間壓縮?
ACM總結——動態規劃(3)空間壓縮 https://blog.csdn.net/nameofcsdn/article/details/106507259
再看看什麼叫自帶空間壓縮的降維描述:
例4:力扣OJ 1218. 最長定差子序列 https://blog.csdn.net/nameofcsdn/article/details/106418150
給定差值dif,求最長等差子序列
如果數組沒有重複的數,那就簡單,ans[arr[i]]=ans[arr[i]-dif]+1
如果有重複的數,那麼相同的數如何選取?
自然是取第i個數之前,等於arr[i]-dif且ans值最大的那個,但是如果搜索的話就會超時,必須在O(1)的時間內找到這個數或者找到它的ans值。
所以我們除了需要知道ans[arr[i]]表示以第i個數結尾的最長等差子序列之外,還需要確定,ans[x]表示啥?
ans[x]=ans[arr[j]],其中j=max{j | arr[j]=x,j<i}
沒錯,這麼一個精準的形式化描述,讓我們意識到,ans[x]的含義中包含了i這個變量,也就是說ans數組的值的含義是隨着時間一直在變化的,這其實是隱含了空間壓縮。