我僅一屆平凡人
對於某些dp的狀態轉移方程,我們可以寫成一種形式:
f [i
]=
minl(
i)≤j
≤r(i
)f[i] = \min_ \
f[i]
=minl(
i)≤j
≤r(i
)在這種模型中,j取值的範圍都是關於i的一次單調函式val
(i,j
)val(i, j)
val(i,
j)是關於i,j的多項式函式。我們將其稱為1d/1d的動態規劃。在上述模型中,如果多項式val
(x,y
)val(x, y)
val(x,
y)的每一項僅與i或j中的一項有關,我們可以使用單調佇列進行優化。
李煜東藍皮書上,給出三個例子。
例1:
給定乙個n長度的序列(有負數),選擇乙個長度不超過m的子段,使子段的所有數的和最大。我處理出字首和s[i
]s[i]
s[i]
答案可以表述成:
a ns
=max1
≤i≤n
}ans = \max_\ \ \}
ans=
max1≤i
≤n}
此時我們發現它符合上述模型。那麼,我們是怎麼通過單調佇列進行優化的呢?我們不妨設兩個位置j,k並滿足:k < j < i。並且s[k
]≥s[
j]
s[k]\ge s[j]
s[k]≥s
[j]這時,我們可以知道:k絕對不可能是最優解。這不僅取決於j的字首和比k小而j更優。還因為j的位置比k靠前(長度更短),我們在後期有更多的空間選擇。此時我們將所有決策按照遍歷順序,維護成乙個單調遞增的佇列。可以知道:最優子結構由且僅由佇列中的決策產生。
藍皮書給出的**:
這個例子其實僅是乙個單調佇列的題目,不怎麼涉及dp。int l =
1, r =1;
q[i]=0
;for
(int i =
1; i <= n; i++
)
例2:poj 1821 fence
我們設f[i
,j
]f[i, j]
f[i,j]
為考慮前i個工匠,刷前j個木板,能獲得的最大報酬。我們可以寫成轉移方程:
f [i
,j]=
maxj−
li≤k
≤si−
1f[i, j] = \max_ \
f[i,j]
=maxj−
li≤
k≤si
−1
這裡注意摒棄i的干擾,這裡的i只是表示階段,不參與當前階段的決策。這裡的k是模型中的j,這裡的j是模型中的i。
對與每乙個階段,我們發現,隨著j的遞增,j−l
ij-l_i
j−li
線性遞增,且val函式符合模型中的定義,可以使用單調佇列優化!這時,我們隨意找出兩個位置k1,
k2(k
1
−1
)k_1,k_2(k_1 < k_2 < s_i-1)
k1,k2
(k1
−1)
且k
2k_2
k2的決策優於k
1k_1
k1此時k
1k_1
k1為完全無用的決策。所以我們依靠轉移方程維護乙個遞減的單調佇列。
在這個題中,我們可以看到,首先對於每乙個i階段,我們初始化單調佇列:
我們在j−lint l =
1, r=0;
for(
int k =
max(
0, a[i]
.s - a[i]
.l); k <= a[i]
.s -
1; k++
)
i≤k≤
si−1
j-l_i \le k \le s_i - 1
j−li≤
k≤si
−1的範圍內初始化單調佇列。因為右端點是不變的。我們只有縮左端點就行了。
下面是完整ac**:for
(int j =
1; j <= n; j++
)}
例3:o(nm)解多重揹包。#include
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
struct node
a[110];
int f[
110]
[16005
], q[
16005];
bool
cmp(node a, node b)
intcalc
(int i,
int k)
intmain()
for(
int j =
1; j <= n; j++)}
}printf
("%d\n"
, f[m]
[n])
;return0;
}
對於多重揹包,我們處理樸素的計數,還可以通過二進位制壓縮進行優化,但是使用單調佇列優化,我們可以講複雜度衰減為o(nm)。
我們通過模擬樸素多重揹包發現:在每個階段,每次狀態的轉移的位置都是成倍的。例如。對於p
pp點,他只能轉移到p+v
i,p+
2∗vi
,p+3
∗v
ip+v_i,p+2 * v_i, p+3*v_i
p+vi,
p+2∗
vi,
p+3∗
vi等,所以我們所有狀態,按照%v
iv_i
vi的餘數分為等價類。對於每乙個餘數u
uu有狀態轉移方程:
f [u
+p∗v
i]
=maxp
−ci≤
k≤p−
1f[u+p*v_i]=\max_\
f[u+p∗
vi]
=maxp−
ci≤
k≤p−
1同理符合上述模型。**不想打了。。。直接看書吧。
回頭學一波斜率優化就ok了。。。。。。。
單調佇列優化動態規劃
lj 那些又遠又差的,我們就不要了 luogup1725 琪露諾 在幻想鄉,琪露諾是以笨蛋聞名的冰之妖精。某一天,琪露諾又在玩速凍青蛙,就是用冰把青蛙瞬間凍起來。但是這只青蛙比以往的要聰明許多,在琪露諾來之前就已經跑到了河的對岸。於是琪露諾決定到河岸去追青蛙。小河可以看作一列格仔依次編號為0到n,琪...
BZOJ1563 詩人小G(1d1d動態規劃)
小g是乙個出色的詩人,經常作詩自娛自樂。但是,他一直被一件事情所困擾,那就是詩的排版問題。一首詩包含了若干個句子,對於一些連續的短句,可以將它們用空格隔開並放在一行中,注意一行中可以放的句子數目是沒有限制的。小g給每首詩定義了乙個行標準長度 行的長度為一行中符號的總個數 他希望排版後每行的長度都和行...
動態規劃之單調佇列優化
先上一道單調佇列動態規劃的模板題 這道題很明顯是一道dp題,可以通過兩個for迴圈就能得到結果,但是n,l,r太大了,兩層for迴圈就超時了,所以我們得用單調佇列來優化。動態規劃一般類如 dp i min dp j f j 0 j i 因為j是從0開始的,使用我們可以用乙個變數記錄dp j f j ...