動態規劃中的單調佇列優化

2021-08-07 16:07:36 字數 1900 閱讀 7722

最近經常出現單調佇列,斜率優化的題目。看到周圍的大神們都會做了,我只能跟上去。

要慢慢來,先學單調佇列。

類似這樣的轉移方程可以用到單調佇列: f[

i]=m

ax(g

[j])

+w[i

] 其中,g[j]是乙個與i無關係的數。w[i]只與i有關係。

我們首先開乙個佇列。dp時:

1、先刪掉前面超出範圍的隊頭。

2、利用隊頭轉移。

3、將這個數和隊尾比較,若隊尾不比它優,就刪掉隊尾,直到隊列為空或隊尾比它優。最後將它加進隊尾。

1、單調佇列中的數都在要範圍之內。

2、隊頭最優(不然早被後面的刪掉了)。

3、為什麼不只存隊頭?因為隊頭比較老,若超出範圍就要被刪掉。

description

烽火台又稱烽燧,是重要的軍事防禦設施,一般建在險要或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊;夜晚燃燒乾柴,以火光傳遞軍情,在某兩座城市之間有n個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續m個烽火台中至少要有乙個發出訊號。請計算總共最少花費多少代價,才能使敵軍來襲之時,情報能在這兩座城市之間準確傳遞。

input

第一行:兩個整數n,m。其中n表示烽火台的個數,m表示在連續m個烽火台中至少要有乙個發出訊號。接下來n行,每行乙個數wi,表示第i個烽火台發出訊號所需代價。

output

一行,表示答案。

sample input

5 3

1 2

5 6

2sample output

4data constraint

對於50%的資料,m≤n≤1,000 。 對於100%的資料,m≤n≤ 100,000,wi≤100。

在單調佇列的題中,這是一道水題了。

設f[i]表示i必須選時最小代價。

初值:

f[0]=0 f[1..n]=∞

方程:

f[i]=min(f[j])+w[i]

並且max(0,i-m)<=j沒有單調佇列的**

#include 

#include

#include

using

namespace

std;

#define i_o(x) freopen(""#x".in","r",stdin);freopen(""#x".out","w",stdout)

int n,m;

int w[100001];

int f[100001];

int main()

for (i=m;i<=n;++i)

我們發現這個方程可以以單調佇列實現,用單調佇列存好最優決策點,就可以將時間複雜度從o(nm)降到o(n)。

正解**

#include 

#include

#include

using

namespace

std;

#define i_o(x) freopen(""#x".in","r",stdin);freopen(""#x".out","w",stdout)

int n,m;

int w[100001];

int que[100001],head=0,tail=0;

int f[100001];

int main()

int ans=0x7f7f7f7f;

for (i=n-m+1;i<=n;++i)

ans=min(ans,f[i]);

printf("%d\n",ans);

}

單調佇列優化動態規劃

lj 那些又遠又差的,我們就不要了 luogup1725 琪露諾 在幻想鄉,琪露諾是以笨蛋聞名的冰之妖精。某一天,琪露諾又在玩速凍青蛙,就是用冰把青蛙瞬間凍起來。但是這只青蛙比以往的要聰明許多,在琪露諾來之前就已經跑到了河的對岸。於是琪露諾決定到河岸去追青蛙。小河可以看作一列格仔依次編號為0到n,琪...

動態規劃之單調佇列優化

先上一道單調佇列動態規劃的模板題 這道題很明顯是一道dp題,可以通過兩個for迴圈就能得到結果,但是n,l,r太大了,兩層for迴圈就超時了,所以我們得用單調佇列來優化。動態規劃一般類如 dp i min dp j f j 0 j i 因為j是從0開始的,使用我們可以用乙個變數記錄dp j f j ...

hdu 3401 單調佇列優化動態規劃

思路 動態方程很容易想到dp i j max dp i j dp i w 1 j k k ap i dp i w 1 j k k bp i dp i j 表示第i天擁有j個石頭的最大價值。其實每次求得都是最有策略,所有dp i w 1 表示的就是i w 1以前的最優,故不同往前遍歷。那麼主要需要優化...