斜率優化dp HDU3507

2021-08-01 00:12:37 字數 1800 閱讀 4991

世界真的很大

上週學了斜率優化dp,慚愧昨天才搞懂,花了一天整理了一下思緒總結如下:

許多樸樹的dp轉移方程可以寫成 f[i]=f[j]+w[i] 的格式,這就意味著i的決策僅僅取決於j的決策優劣,可以由單調佇列把n^2優化到n,這裡不贅述。

但更多的轉移方程並不能化簡成如下格式,比如這道hdu3507:

先敘述下題意,給出乙個陣列,將其分為幾組,每一組算出其和的平方加上給定數m,將每一組的值求和然後輸出,求最小值。

提意明確,列出狀態轉移方程:

f[i]=f[j]+m+(sum[i]-sum[j])^2

注意,這個方程並不能用單調佇列解決,因為i的決策不僅取決於j,還取決於(sum[i]-sum[j])^2,這就無法對f進行單調佇列儲存。

對方程進行數學處理,假定j和k,在決策i時,j比k優:

dp[j]+m+(sum[i]-sum[j])^2<dp[k]+m+(sum[i]-sum[k])^2

直接開啟消元得出:

dp[j]+sum[j]^2-2*sum[i]*sum[j]< dp[k]+sum[k]^2-2*sum[i]*sum[k]

移項相除得:

dp[j]+sum[j]^2-(dp[k]+sum[k]^2)/2*(sum[j]-sum[k])<sum[i]

仔細一看的話,左邊就是乙個只關於j,k的斜率表示式了。定義左邊為g(j,k)<sum[i]的話,說明在決策i時,j比k優,那麼可以單調佇列來維護斜率,最小的斜率最優且在對首。

為什麼可以這樣呢?再解釋一遍。

因為我們發現,在比較決策i時的前驅決策j,k誰優時,得到了乙個關乎斜率的等式g(j,k),g(j,k)<sum[i]時,說明j比k優,就是說,凡是斜率比g(j,k)小,那一定沒有sum[i]大,如g(a,b)<g(b,c)<g(c,d)….<g(j,k)<sum[i],那就是a沒有b優,b沒有c優。。。如果用單調斜率的佇列,就可以瞬間排除j以前的選項,排除選項,即為優化。

現在我們的單調佇列維護的就是斜率的單調遞增了,在決策i時,凡是對首斜率比sum[i]小的,都可以直接彈出去,因為不優,如上解釋,每次隊首一定是最優的,因為後面的都大於sum[i]了,不滿足g(h,h+1)

bool check_h(int i)

隊尾的話直接按graham-scan(古來哈姆–斯侃胡)的方法維護下凸的凸包就行了,但注意的是,我們維護的不是整個凸包而是零碎的小節,**:

bool check_t(int i)

x和y分別是之前數學證明裡的分子和分母,因為太長了就寫成了函式,如下:

int x(int u,int v)

int y(int u,int v)

完整**如下:

#include

int sum[500050],f[500050],h,t,n,m,state[500050];

intx(int u,int v)

inty(int u,int v)

bool check_h(int i)

bool check_t(int i)

int main()

h=1,t=1,state[1]=0;

for(int i=1;i<=n;i++)

printf("%d\n",f[n]);

}return

0;}

恩,就是這樣;

HDU3507 斜率優化

r 題意 把n分成任意段 每段中連續 每一段代價 ci m 求總的最小代價 i l作為提醒自己的經驗題,即使再水也要記住坑點 其實是自己被坑的地方 斜率優化裸題 首先定義dp i 表示把前i個處理好的最小代價 dp i min 一看這個轉移就是n 2的,我們來搞成o n 的。h i m sum i ...

hdu 3507 斜率優化

我的第一道斜率優化。就這道題而言,寫出原始的方程 dp i min o n 2 的複雜度肯定超時,要麼優化轉移,要麼重寫方程。斜率優化的思想就是減少不必要的列舉 即不列舉肯定不會成為決策點的j 我們考慮兩個位置p 選擇q比選擇p優 當且僅當 dp q sum i sum q 2 m dp p sum...

hdu3507斜率優化dp

這題 n可能取500000,o n 2 就會超時吧,所有只能優化。注意到這題的動態規劃方程 dp i max dp j sum i sum j 2 m 化簡下得 dp i max dp j sum i 2 sum j 2 2 sum i sum j 無法直接用單調佇列優化,i和j不能分開。假設j比k...