1. 程式人生 > >HDU 2829 Lawrence【斜率優化dp】

HDU 2829 Lawrence【斜率優化dp】

題意:大概就是給你n(1<=n<=1000)個數,要你將其分成m + 1(0<=m<n)組,要求每組數必須是連續的而且要求得到的價值最小。一組數的價值定義為該組內任意兩個數乘積之和,如果某組中僅有一個數,那麼該組數的價值為0。如:

將“4 5 1 2”分成一組得到的價值為:4*5 + 4*1 + 4*2 + 5*1 + 5*2 + 1*2 = 49;

將“4 5 1 2”分成“4 5”和“1 2”兩組得到的價值為:4*5 + 1*2 = 22;

將“4 5 1 2”分成“4”和“5 1 2”兩組得到的價值為:0 + 5*1 + 5*2 + 1*2 = 17。

分析:本題可以用動態規劃來解決,但需要斜率優化。

定義dp[i][j]表示將前j個數分成i組所得到的價值,sum[i]表示前i個數之和,w[i]表示前i個數分成一組的價值,則:

dp[i][j] = min{dp[i-1][k] + val(k+1, j)} (i-1<=k<j),val(k+1, j)為將第k+1~j個數分為一組的價值。對該式變形得:

dp[i][j] = min{dp[i-1][k] + w[j] - w[k] - sum[k]*(sum[j] - sum[k])}

          = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[j]} + w[j] (i-1<=k<j).

然後,就可以對該dp進行斜率優化。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 1010;
int n, m;
int a[maxn], sum[maxn], w[maxn];
int dp[maxn][maxn];
int q[maxn], head, tail;

int dy(int x, int j, int i)
{
    return dp[x][i] - w[i] + sum[i] * sum[i] - (dp[x][j] - w[j] + sum[j] * sum[j]); 
}

int dx(int j, int i)
{
    return sum[i] - sum[j];
}

void DP()
{
    for (int i = 1; i <= n; ++i) {
        dp[1][i] = w[i];
    }
    for (int i = 2; i <= m + 1; ++i) {
        head = tail = 0;
        q[tail++] = i - 1;
        for (int j = i; j <= n; ++j) {
            while (tail - head >= 2) {
                int p = q[head], k = q[head+1];
                if (dy(i - 1, p, k) < sum[j] * dx(p, k)) {
                    head++;
                } else {
                    break;
                } 
            }
            dp[i][j] = dp[i-1][q[head]] + w[j] - w[q[head]] - sum[q[head]] * (sum[j] - sum[q[head]]);
            while (tail - head >= 2) {
                int p = q[tail-2], k = q[tail-1];
                if (dy(i - 1, p, k) * dx(k, j) >= dx(p, k) * dy(i - 1, k, j)) {
                    tail--;
                } else {
                    break;
                }
            }
            q[tail++] = j;
        }
    }
    printf("%d\n", dp[m+1][n]); 
}

int main()
{
    while (scanf("%d%d", &n, &m) != EOF) {
        if (n == 0 && m == 0) break;
        sum[0] = 0;
        w[0] = 0;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            sum[i] = sum[i-1] + a[i];
            w[i] = w[i-1] + sum[i-1] * a[i]; 
        }
        DP();
    }
    return 0;
}


相關推薦

HDU 2829 Lawrence斜率優化dp

題意:大概就是給你n(1<=n<=1000)個數,要你將其分成m + 1(0<=m<n)組,要求每組數必須是連續的而且要求得到的價值最小。一組數的價值定義為該組內任意兩個數乘積之和,如果某組中僅有一個數,那麼該組數的價值為0。如: 將“4 5 1 2

1010. [HNOI2008]玩具裝箱TOY斜率優化DP

ont 位長 str 北京 clas 斜率 out hellip hnoi Description   P教授要去看奧運,但是他舍不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓 縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。P教授

1096. [ZJOI2007]倉庫建設斜率優化DP

表示 倉庫 單位 符號 output while 目前 data 兩個 Description   L公司有N個工廠,由高到底分布在一座山上。如圖所示,工廠1在山頂,工廠N在山腳。由於這座山處於高原內 陸地區(幹燥少雨),L公司一般把產品直接堆放在露天,以節省費用。

Codeforces 311B Cats Transport斜率優化DP

LINK 題目大意 有一些貓,放在一些位置,人一步移動一個位置 給出每個貓出現的時間,每個人可以自由安排其出發時間,沿途已經出現的貓撿起,貓等待的時間是被減去的時間減去出現的時間 貓可以等人,人不能等貓 現在有P個人,問貓等待的總時間T最小是多少。 思路 首先可以算出要撿起每個貓最早出發的時間是多

BZOJ1010 ||洛谷P3195 [HNOI2008]玩具裝箱TOY斜率優化DP

Time Limit: 1 Sec Memory Limit: 162 MB Description P教授要去看奧運,但是他舍不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓

BZOJ3672: [Noi2014]購票CDQ分治點分治斜率優化DP

Description 今年夏天,NOI在SZ市迎來了她30週歲的生日。來自全國 n 個城市的OIer們都會從各地出發,到SZ市參加這次盛會。 全國的城市構成了一棵以SZ市為根的有根樹,每個城市與它的父親用道路連線。為了方便起見,我們將全國的 n 個城市用 1 到 n 的整數編號。其中SZ市的編號為 1。

HDU3507 Print Article 斜率優化DP

傳送門 sum[i]=∑ij=0c[j] d[i]=min{d[j]+M+(sum[i]−sum[j])2|j<i} 若d[a]+M+(sum[i]−sum[a])2<d[b]+M

BZOJ1297 [SCOI2009]迷路 矩陣優化dp

return 必須 pan 但是 stream names mem urn cout 題目 windy在有向圖中迷路了。 該有向圖有 N 個節點,windy從節點 0 出發,他必須恰好在 T 時刻到達節點 N-1。 現在給出該有向圖,你能告訴windy總共有多少種不同的路徑

HDU - 3045 - Picnic Cows [ 斜率優化dp ]

Problem Describe It’s summer vocation now. After tedious milking, cows are tired and wish to take a holiday. So Farmer Carolina considers havi

HDU - 3507 , Print Article [ 斜率優化dp , 良心部落格 ]

題目標題:列印文章 給出N個單詞,每個單詞有個非負權值Ci,現在要將它們分成連續的若干段,每段的代價為此段單詞的權值和的平方,還要加一個常數M,即。現在想求出一種最優方案,使得總費用之和最小。 輸入格式 包含多組測試資料,對於每組測試資料。 第一行包含兩個整數N和M(0&l

HDU 3507 Print Article——斜率優化dp

首先不難推出這道題的狀態轉移方程:dp[i]=min{dp[j]+(sum[i]-sum[j])^2|0<j<i} 假設有k<j,j比k更優當且僅當dp[j]+(sum[i]-sum[j])^2<=dp[k]+(sum[i]-sum[k])^2 化

HDU.2829.Lawrence(DP 斜率優化)

digi pos == spa tchar str 轉移 方程 決策單調 題目鏈接 \(Description\)   給定一個\(n\)個數的序列,最多將序列分為\(m+1\)段,每段的價值是這段中所有數兩兩相乘的和。求最小總價值。 \(Solution\)   寫到這突

HDU - 2829 Lawrence [ 斜率優化dp ]

題目連結 : HDU - 2829 題意 : 給出一條筆直無分叉的鐵路上有n個倉庫,每個倉庫有一個v[i]代表價值; 每兩個倉庫之間算作一段鐵路,現在有m次攻擊機會,一次攻擊可以炸燬一段鐵路; m次攻擊後,剩餘的總價值為:Σ(v[i]*v[j]),i和j為所有任意兩個互相

bzoj4518[Sdoi2016]征途 斜率優化dp

end 時間復雜度 leg size cpp print ++ 需要 () 原文地址:http://www.cnblogs.com/GXZlegend/p/6812435.html 題目描述 Pine開始了從S地到T地的征途。 從S地到T地的路可以劃分成n段,相鄰兩段路的

bzoj3675[Apio2014]序列分割 斜率優化dp

sof turn col 兩個 led 輸入 分數 包含 class 原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 題目描述 小H最近迷上了一個分隔序列的遊戲。在這個遊戲裏,小H需要將一個長度為n的非負整數序列分

bzoj1096倉庫建設——斜率優化dp

getch ron con span bdd nss typedef a20 family 題目鏈接 我們用sum[i]表示前i個工廠的產品數之和,b[i]表示x[i]*p[i]的前綴和,因此第j+1~i個工廠的產品運到第i個工廠的代價就是   (sum[i]-sum[

斜率優化DP和四邊形不等式優化DP整理

dex add ive mat 整理 off code 斜率dp 好的 當dp的狀態轉移方程dp[i]的狀態i需要從前面(0~i-1)個狀態找出最優子決策做轉移時 我們常常需要雙重循環 (一重循環跑狀態 i,一重循環跑 i 的所有子狀態)這樣的時間復雜度是O(N^2)而 斜

BZOJ 1492 [NOI2007]貨幣兌換Cash 斜率優化DP

ostream 解決 double col esp ash pre 優秀 不用   先說一下斜率優化:這是一種經典的dp優化,是OI中利用數形結合的思想解決問題的典範,通常用於優化dp,有時候其他的一些決策優化也會用到,看待他的角度一般有兩種,但均將決策看為二維坐標系上的點

筆記篇斜率優化dp(五) USACO08MAR土地購(征)買(用)Land Acquisition

body 遞增 std char log lin 關鍵字排序 斜率優化 getchar 好好的題目連個名字都不統一.. 看到這種最大最小的就先排個序嘛= =以x為第一關鍵字, y為第二關鍵字排序. 然後有一些\(x_i<=x_{i+1},且y_i<=y_{i+

筆記篇斜率優化dp(一) HNOI2008玩具裝箱

公式 現在 getchar() 就是 clu cst 差距 直接 source 斜率優化dp 本來想直接肝這玩意的結果還是被忽悠著做了兩道數論現在整天渾渾噩噩無心學習甚至都不是太想頹廢是不是藥丸的表現各位要知道我就是故意要打刪除線並不是因為排版錯亂反正就是一個del標簽嘛