HDU2829 Lawrence(斜率最佳化dp)

來源:互聯網
上載者:User

標籤:blog   os   io   資料   for   ar   div   amp   

學了模板題之後上網搜下斜率最佳化dp的題目,然後就看到這道題,知道是斜率dp之後有思路就可以自己做不出來,要是不事Crowdsourced Security Testing道的話那就說不定了。

題意:給你n個數,一開始n個數相鄰的數之間是被東西連著的,對於連著的一片的數,它們的價值就是兩兩乘積的和。所以4 5 1 2一開始就是4*5+4*1+4*2+5*1+5*2+1*2... 注意到兩兩乘積的和其實是可以這麼算的((a1+a2+a3+..an)^2-(a1^2+a2^2+....))/2。現在我可以在數與數之間切m刀,問切完之後的最小价值是多少。

一個自然的想法是定義dp[n][t]表示的是前n個數被切了t刀的最小价值,不難發現方程是可以這麼轉移的

dp[i][t]=dp[j][t-1]+((sum[i]-sum[j])*(sum[i]-sum[j])-(d[i]-d[j]))/2  (j<i) 其中d[i]表示前i個數的平方的和

所以這個方程是1個三維的dp,對於1000的資料量是行不通的,所以仿照斜率最佳化的思路,我們可以嘗試寫出當 k<j時,j比k更優的方程,即:

dp[j][t-1]+((sum[i]-sum[j])*(sum[i]-sum[j])-(d[i]-d[j]))/2 < dp[k][t-1]+((sum[i]-sum[k])*(sum[i]-sum[k])-(d[i]-d[k]))/2

經過化簡,我們可以得到一個這樣的東西:

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

顯然又是一個斜率式子,利用先前推導的性質我們可以知道,我們每次更新的時候其實就是利用t-1層的資訊推出t層的資訊,推的時候實際有效值也是一個下凸的點集,這個和上一題不一樣之處就在於要更新m次,每次隊列都要重新入隊,但總體來說還是一樣的,由於斜率最佳化后里層的dp達到線性,所以最後複雜度出來是O(n^2)的,仍然要注意之所以一開始可以彈隊首是因為 sum[i]是遞增的。

#pragma warning(disable:4996)#include <iostream>#include <cstdio>#include <vector>#include <algorithm>#include <cstring>#include <string>#include <cmath>using namespace std;#define ll long long#define maxn 1100ll dp[maxn][maxn];ll a[maxn];ll sum[maxn];ll d[maxn];int n, m;ll getup(int i, int j, int t){return (2 * dp[i][t] + sum[i] * sum[i] + d[i]) - (2 * dp[j][t] + sum[j] * sum[j] + d[j]);}ll getdown(int i, int j){return 2 * (sum[i] - sum[j]);}int que[maxn];int qh, qt;int main(){while (cin >> n >> m&&(n||m)){a[0] = d[0] = sum[0] = 0;for (int i = 1; i <= n; ++i){scanf("%I64d", &a[i]);sum[i] = sum[i - 1] + a[i];d[i] = d[i - 1] + a[i] * a[i];}dp[0][0] = 0;for (int i = 1; i <= n; ++i){dp[i][0] = dp[i - 1][0] + a[i] * sum[i - 1];}for (int x = 1; x <= m; ++x){dp[0][x] = 0;qh = qt = 0;que[qt++] = 0;for (int i = 1; i <= n; ++i){while (qh + 1 < qt && getup(que[qh + 1], que[qh], x - 1) <= sum[i] * getdown(que[qh + 1], que[qh])){qh++;}dp[i][x] = dp[que[qh]][x - 1] + ((sum[i] - sum[que[qh]])*(sum[i] - sum[que[qh]]) - (d[i] - d[que[qh]])) / 2;while (qh + 1 < qt && getup(i, que[qt - 1], x - 1)*getdown(que[qt - 1], que[qt - 2]) <= getup(que[qt - 1], que[qt - 2], x - 1)*getdown(i, que[qt - 1])){qt--;}que[qt++] = i;}}printf("%I64d\n", dp[n][m]);}return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.