ZJOI 2007 倉庫建設

2021-08-30 02:45:02 字數 1467 閱讀 4136

注意到我們所有的東西都只能轉移到後面,那麼可以考慮dp

用dp[i]表示以i結尾建立倉庫的最小花費

那麼dp[i] = min(dp[i], dp[j] + w[i] + sigma(dis[i] - dis[k]) * num[k])

這個dp直接轉移是n ^ 2

考慮優化這個dp

然後他是由前面所有的轉移過來,而且還有其他的陣列來計算答案,一般的資料結構解決不了這個問題,那麼就xjb劃式子搞搞,然後就可以推出乙個東西

用sumd[i] 表示num[i] * dis[i]的字首和

用sumn[i]表示num[i]的字首和

考慮乙個k比j更優秀,那麼可以推出 dis[i] > (dp[k] + sumd[k] - dp[j] - sumd[j]) / (sumn[k] - sumn[j]) 

然後就是斜率優化的慣用套路

每次新加入乙個的時候看看隊首是否合法,把不合法的全部彈掉,然後更新dp值

例如 while (head < tail && slope(q[head], q[head + 1]) < 1.0 * dis[i]) head++;

然後得到dp[i]的值

再看看當前值是否能比隊尾值,把廢物搞掉

例如 while (head < tail && slope(q[tail - 1], q[tail]) > slope(q[tail], i)) tail--;

然後把這個b加入佇列中

斜率優化主要是要看的出來,然後能推出式子,最重要的是要能劃出乙個斜率的形式,例如y[i] - y[j] / x[i] - x[j]這種

**如下

#include#include#include#include#define ll long long

using namespace std;

int readint()

while (ch >= '0' && ch <= '9')

return rt * f;

}ll readll()

while (ch >= '0' && ch <= '9')

return rt * f;

}const int maxn = 1e6 + 5;

int n;

ll num[maxn], dis[maxn], w[maxn], sumd[maxn], sumn[maxn], dp[maxn];

int q[maxn << 1];

double slope(int k, int j)

int main()

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

int head = 1, tail = 0;

q[++tail] = 0;

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

printf("%lld\n", dp[n]);

return 0;

}

ZJOI2007 倉庫建設

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

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 之後把式子變個型套斜率優化就好了...

ZJOI 2007 倉庫建設

這道題不算很難,這裡我提供兩種做法。設 dp i 為在 i 位上設定倉庫,前面工廠都解決了的最小花費。首先我們可以列出 dp 式 dp i min dp j sigma p k x i x k c i 即 dp i min dp j x i sigma p k sigma p k x k c i 我...