有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...