嘟嘟嘟
剛開始推了乙個\(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 之後把式子變個型套斜率優化就好了...