ZJOI2007 倉庫建設

2022-05-09 11:12:11 字數 1342 閱讀 5439

嘟嘟嘟

剛開始推了乙個\(o(n ^ 2)\)的dp方程,但是需要倒著來,然後斜率優化的時候出現了各種錯誤,最終還是放棄。

換乙個正著來的吧。

令\(dp[i]\)表示在\(i\)建倉庫時的最小花費,則

\[dp[i] = min _ ^ \ ^ \} + c[i]

\]把裡面的\(\sum\)拆開,得到\(x[i] * \sum _ ^ p[k] - \sum _ ^ d_k * p_k\),發現這個可以用兩個字首和優化到\(o(1)\)。

於是\[dp[i] = min _ ^ \ + c[i]

\]然後就是正常的斜率優化了。

簡單導一導,得到

\(y = dp[j] + sum[j]\)

\(k = x[i]\)

\(x = sump[j]\)

\(dp[i] = y - kx + d[i] * sump[i] - sum[i] + c[i]\)

發現\(x, k\)都是單調遞增,很開心,維護下凸包即可。

#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define enter puts("")

#define space putchar(' ')

#define mem(a, x) memset(a, x, sizeof(a))

#define rg register

typedef long long ll;

typedef double db;

const int inf = 0x3f3f3f3f;

const db eps = 1e-8;

const int maxn = 1e6 + 5;

inline ll read()

inline void write(ll x)

int n, d[maxn], p[maxn], c[maxn];

ll sump[maxn], sum[maxn], dp[maxn];

int q[maxn], l = 0, r = 0;

#define k(i) d[i]

#define x(i) sump[i]

#define y(i) (dp[i] + sum[i])

db slope(int i, int j)

int main()

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

write(dp[n]), enter;

return 0;

}

ZJOI2007 倉庫建設

l公司有n個工廠,由高到底分布在一座山上。如圖所示,工廠1在山頂,工廠n在山腳。由於這座山處於高原內陸地區 乾燥少雨 l公司一般把產品直接堆放在露天,以節省費用。突然有一天,l公司的總裁l先生接到氣象部門的 被告知三天之後將有一場暴雨,於是l先生決定緊急在某些工廠建立一些倉庫以免產品被淋壞。由於地形...

ZJOI 2007 倉庫建設

注意到我們所有的東西都只能轉移到後面,那麼可以考慮dp 用dp i 表示以i結尾建立倉庫的最小花費 那麼dp i min dp i dp j w i sigma dis i dis k num k 這個dp直接轉移是n 2 考慮優化這個dp 然後他是由前面所有的轉移過來,而且還有其他的陣列來計算答案...

ZJOI2007 倉庫建設

傳送門 考慮用dp i 表示把前i個地點的物品全部安置好的最小花費。因為物品只能往下運,所以當前這個位置必須建倉庫,dp方程很好想 dp i min p k x i x k c i 用 sum n 表示 sum np i ssum n 表示 sum np i x i 之後把式子變個型套斜率優化就好了...