HDU 3480 Division 斜率優化DP

2021-06-28 19:43:36 字數 1918 閱讀 6519

題意:現在有n個元素的集合s。把集合s劃分成m個子集,每個子集的花費為集合中最大和最小元素的差的平方。

求如何劃分,才能總的代價最小。

思路:首先要注意到,因為集合中的元素具有無序性,我們只需知道集合中最大和最小的元素就能算出代價,也能把集合劃分出來。

所以,我們把所有元素進行排序,這樣,最小的元素和最大的元素的位置就是已知的了。

定義:dp[i][j]將前j個元素劃分成i個子集得到的最小花費和。

則: dp[

i][j

]=mi

n(dp

[i−1

][k]

+(aj

−ak+

1)2)

,i≤k

≤n初始條件 dp

[1][

j]=(

aj−a

1)2

但是這樣的複雜度是θ(

mn 2

) ,會超時。

注意到出現了平方的形式,且ai

有遞增的性質,這啟發我們可以嘗試一下是否能斜率優化。

將上面的式子變形: dp

[i][

j]=m

in(d

p[i−

1][k

]+a2

k+1−

2aja

k+1)

+a2j

假設t < k < j,如果k比t在j更優,則有 dp

[i−1

][k]

+a2k

+1−2

ajak

+1≤d

p[i−

1][t

]+a2

t+1−

2aja

t+1

變形得: (d

p[i−

1][k

]+a2

k+1)

−(dp

[i−1

][t]

+a2t

+1)a

k+1−

at+1

≤2aj

令g(t,k)

=(dp

[i−1

][k]

+a2k

+1)−

(dp[

i−1]

[t]+

a2t+

1)ak

+1−a

t+1

則 g(t

,k)≤

2aj

同樣,我們可以證明 1.g

(t,k

)≤2a

j≤2a

l,l≥

j 。 2.如果g(

t,k)

≥g(k

,j) 

,k一定不是最優解。

上面的證明說明,我們能用單調佇列來優化尋找最優解的過程。

**如下:

#include

#include

#include

using namespace std;

const int maxn = 10010;

const int maxm = 5010;

int a[maxn];

int dp[maxm][maxn];

int n, m;

intq[maxn];

int head, tail;

int main()

int k = q[head];

dp[i][j] = dp[i - 1][k] + (a[j] - a[k + 1])*(a[j] - a[k + 1]);

while (head + 1

< tail)

q[tail++] = j;}}

printf("case %d: %d\n", icase, dp[m][n]);

}return

0;}

HDU 3480 DP 斜率優化

題意 給你n個數字,然後叫你從這些數字中選出m堆,使得每一堆的總和最小,一堆的總和就是這一堆中最大值減去最小值的平方,最後要使得所有堆加起來的總和最小。思路 對這些數字排序之後,很容易想到dp解法,用dp i j 表示數字i現在在第j堆,那麼轉移方程就是dp i j min dp i j dp k ...

HDU 2829 Lawrence 斜率優化DP

題意 敵人有一條直線形狀的鐵路,上面有n個據點,每個據點有對應的值表示他的價值。據點之間通過鐵路相連。整條鐵路上的戰略價值定義為 i,j 1 in ai aj,其中 i j 表示可以通過鐵路相互到達的兩個據點,ai aj 為對應據點的價值。我們現在能炸毀據點之間的鐵路,但是只能炸掉m段鐵路。希望最小...

Hdu 2993斜率優化

這題是斜率優化的入門題 數形結合在資訊學競賽中的應用中講得很好,這是其中的例二 在此標記個人理解上覺得重要的地方 首先這題求max即看成求最大斜率.include include include using namespace std typedef long long ll const int n...