hdu 3507 斜率優化

2022-06-02 12:39:14 字數 1944 閱讀 1963

我的第一道斜率優化。

就這道題而言,寫出原始的方程:

dp[i] = min

o(n^2)的複雜度肯定超時,要麼優化轉移,要麼重寫方程。

斜率優化的思想就是減少不必要的列舉(即不列舉肯定不會成為決策點的j)。

我們考慮兩個位置p「選擇q比選擇p優」 當且僅當 dp[q]+(sum[i]-sum[q])2+m < dp[p]+(sum[i]-sum[p])2+m

化簡右邊即:

[ (dp[q]+sum2[q])-(dp[p]+sum2[p]) ] / ( sum[q]-sum[p] ) < sum[i]*2

該式可以看成兩個點連線的斜率:( sum[q], dp[q]+sum2[q] ) 與 ( sum[p], dp[p]+sum2[p] ) 兩點。

文字語言就是:「將每個決策位置看成乙個二維座標系下的點,對於兩個決策點,後者比前者優 當且僅當 兩點連線的斜率小於sum[i]*2」

這樣怎麼減少不必要的列舉呢?

可以發現,所有決策點一定是單調不下降的(題中可能出現權值為0,此時有可能出現斜率為正無窮,若m=0,還有可能出現重點,所以計算斜率不要用除法)

上面的b點一定是不會成為最優決策點的,反證法:

如果b成為最優決策點,那麼

2*sum[i]>kab 且 2*sum[i]bc

而顯然kab > kbc ,這樣就推出了2*sum[i]>kab >kbc >2*sum[i],矛盾。

故b不可能成為最優決策點,同理,d也不行,刪掉這些點後,我們剩下的圖形就是乙個下凸的圖形了:

我們維護這樣乙個下凸的圖形到佇列中:

當要查詢i位置的最優決策點時,一直刪除隊首的點,直到隊中的第一條直線的斜率大於2*sum[i]或隊中只有乙個點,此時隊首元素就是最優決策點。

計算完i位置後,要將i位置對應的點加入到佇列中,此時會刪除一些對尾的點,以保持隊中點的下凸性(注意處理重合的點)。

這樣,我們就利用斜率優化掉了很多不必要的列舉,將時間複雜度從o(n^2)降到了o(n)。

1 #include 2

#define ln(a,b) ((b)-(a))

3#define maxn 500010

45 typedef long

long

lng;67

struct

vector

11 vector( lng x, lng y, int

id ) : x(x), y(y), id(id) {}

12 vector operator-( const vector & b ) const

13 lng operator&( const vector & b ) const

16};

17typedef vector point;

1819

intn, m;

20int

cost[maxn];

21lng sum[maxn];

22lng dp[maxn];

2324

intbeg, end;

25point qu[maxn];

2627

intmain()

3637 dp[0] = 0

;38 qu[beg=end=0] = point( 0, 0, 0

);39

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

50 printf( "

%lld\n

", dp[n] );51}

52 }

view code

HDU3507 斜率優化

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

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

hdu3507 動態規劃 斜率優化

解題報告題目 題目大意 將序列 c n 分成若干段,每段的值為 c i 2 m.求序列的最小值。演算法 動態規劃 斜率優化 思路 看到題目以為數字和亂序,就沒想是動歸而是數論。因為所求的值與段數無關,因此設定dp方程時,不需要為段數設定狀態。設 dp i 表示前i段的最小值 則有 dp i min ...