線性動態規划


  准確來說,動態規划是一種思想,而不是一種算法。算導里將它歸結為——高級程序設計技巧。

  在線性結構上進行狀態轉移DP,統稱線性DP。

  線性DP最常見的有: 子集和問題,LIS問題,LCS問題。

  拓展之后有:子段和問題,雜類問題。

1. 子集和問題和硬幣計數問題

子集和問題的一個實例: 〈S,t〉。其中,S={ 1 x , 2 x ,…, n x }是一個正整數的集合,c是一個正整數。子集和問題判定是否存在S的一個子集S1,使得s1中的各元素之和等於c。 這其實就是0/1背包。

硬幣計數問題的一個實例:給出n個正整數組成的集合{a1,a2....an},ka1+ka2+ka3+...kan=T有多少解? 這其實就是0/1背包計數。

背包問題的早期總結來自於dd_engi的背包九講。其中屬於線性DP的部分為:0/1背包,完全背包,多重背包,混合背包,分組背包,二維費用背包。

計數問題的循環和轉移方程和背包問題都非常相似。

 

@練習題。

HDU 1864,浮點數0/1背包。先對價格做個轉化,不然沒法數組轉移。

 

ZOJ3211,貪心0/1背包,首先可以肯定的是,要滿足最大,每天肯定都得取。由於每棵樹增長快慢不同,所以肯定先砍增長慢的,后砍增長快的,權值(j-1)*b+a。

 

HDU 1114,最小化完全背包,初始化全部為inf,轉移條件從max改為min。特判條件兩個:f[V]>=inf代表不可能裝滿,V=0代表空背包。

這題同時也牽扯到最大化背包的初始化問題,如果要求裝滿背包, 則f[0]=0,f[1..V]=-inf。

 

HDU 1712,分組背包。N天,M節課。對於每一天,可以選擇1...M之間任何一節課。注意for(V)循環在for(組)循環外面,才能保證每組只有一個被選。

 

POJ 1276,多重背包。

 

HDU 1171,多重背包。盡可能將總價值半分,先用V/2背包一次,這個結果是最接近V/2的,然后另一個就是V-f[V/2]了。

 

HDU 2844,多重背包可達。需要求的是可以湊出多少種面值。由於錢幣的特殊性(val=cost),所以背包完了之后,判斷f[i]=i的個數即可。

 

POJ 1014,多重背包可達。判斷一堆石子能否分為價值相等的兩堆。特性val=cost,判斷f[V/2]是否等於V/2即可。另外V是奇數可以不用計算。

 

UVA 147,完全背包計數。循環倒過來,根據基礎面值壓縮一下全部面值。

 

HDU 5000, 分組背包計數。2014鞍山網絡賽D題,一個神奇的結論,把所有T值加起來/2就是背包容量,然后每組物品就是0~T[i],注意0值物品不要選,是沒意 義的,實際上是從1~T[i]。WJMZBMR說其實用分組背包是TLE的,這題比賽時候就放水了,T^T。至於結論證明,orz不會。

 

2.LIS問題

     LIS 的轉移方程f[i]=max(a[i],f[j]+a[i]),其中j的范圍是1...i-1,常規是掃一遍O(n),借助二分查找可以O(logn), 也就是所謂的二分優化。LIS分為單維度,和雙維度兩類。單維度直接DP,雙維度需要先sort,讓其中一個維單調,然后對另一個維DP。

 

@練習題

POJ 2533,裸題,可以練習二分優化的使用。


POJ 1609,雙維度LIS。鋪磚頭,新的磚放舊的磚上面,必須滿足l>=l',m>=m',先對l排序,然后對m DP。注意本題的第一維可以相等。如果要求不等,則DP條件里還要對l維特判,如Vijos 1336。


POJ 3616,雙維度LIS。擠牛奶,多個時間段,要求不能重疊,且擠完后休息r時間。先對開始時間排序,然后對結束時間DP。條件由原來的遞增改為j.end+r<=i.start。


Vijos 1303,單維度LIS。導彈攔截,第一問是LDS,第二問是LIS。第二問是LIS的原因是,只要單調增就得+1,所以LIS是正確的。LIS+LDS=n,倆個正好互補。


Vijos 1336,雙維度LIS。看起來像個迷宮DP,其實不是。想要距離最短,就得盡可能走特殊邊。但是特殊邊是有要求的,后一個特殊邊x>x',y>y',DP即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM