圍欄(dp 單調佇列)

2021-10-05 18:53:59 字數 1249 閱讀 6936

有n塊木板從左到右排成一行,有m個工匠對這些木板進行粉刷,每塊木板至多被粉刷一次。

第 i 個木匠要麼不粉刷,要麼粉刷包含木板 si 的,長度不超過 lili 的連續的一段木板,每粉刷一塊可以得到 pi 的報酬。

不同工匠的si不同。

請問如何安排能使工匠們獲得的總報酬最多。

輸入格式

第一行包含兩個整數n和m。

接下來m行,每行包含三個整數li,pi,si。

輸出格式

輸出乙個整數,表示結果。

資料範圍

1≤n≤16000,

1≤m≤100,

1≤pi≤10000

輸入樣例:

8 4

3 2 2

3 2 3

3 3 5

1 1 7

輸出樣例:

17
dp思路:

狀態表示:

用f[i][j]表示用前i個工匠,刷到第j塊木板的所有方案的集合的最大總報酬

狀態計算:

根據最後乙個不同點:當前第i個工匠刷或不刷將集合劃分為兩類:

第i個工匠不刷時,f[i][j]=f[i-1][j]

第i個工匠刷時,根據第j塊木板刷不刷分為兩類:

第j塊木板不刷時,f[i][j]=f[i][j-1]

第j塊木板刷時,根據刷的區間起點變數k,終點固定為j,所以長度為j-k,  則f[i][j]=max(f[i][j-k]+(j-k)*p[i])

注意:k的取值範圍,最多刷 l 塊木板,所以j-k>=l  =>  k>=j-l, 同時,必須包含s, 所以k因此,就是求在[j-l,s-1]的區間所示視窗內,求f[i][j-k]+(j-k)*p[i]的最大值,可以用單調佇列的滑動視窗來維護這一動態區間(j不變,但作為起點的k是變化的)內f[i][j-k]+(j-k)*p[i]的最大值。

完整**:

#include #include #include using namespace std;

const int maxn=16510,m=110;

struct people

if(j}

}cout

}

單調佇列優化DP 圍欄

這道題只有兩種狀態,乙個是工人,乙個是磚,那麼我們就可以定義我們的函式f i j f i j f i j 代表的是到第i個工人刷到j塊磚所花費的代價。定義完狀態過後我們開始劃分集合,第一種就是第i個工人不刷那麼就是f i 1 j f i 1 j f i 1 j 然後就是第i個工人刷,刷的話又分不刷第...

單調佇列 DP

烽火傳遞 description 烽火台又稱烽燧,是重要的防禦設施,一般建在險要處或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊 夜晚燃燒乾柴,以火光傳遞軍情。在某兩座城市之間有n個烽火台,每個烽火台發出訊號都有一定的代價。為了使情報準確的傳遞,在m個烽火台中至少要有乙個發出訊號。現輸...

單調佇列DP 斜率DP

考慮到知識點是單調佇列,考慮怎麼使用單調佇列 首先說明一點,小天使可以選擇當前時刻鋼琴是否移動 並非一次就要一段時間 考慮dp方程,由於每次只能走乙個方向,選擇不了,其實就相當於乙個一維的dp了 以往上 北 為例 t為第t段時間 f t i j max 變形為 f t i j max i 然後把 f...