[Bzoj1096][ZJOI2007]仓库建设(斜率优化)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1096

一开始想了想费用流,然后被数据范围pass掉了,感觉dp更可行一些。

只想到一个O(n2)的做法,看到式子比较复杂,就感觉像是斜率优化。

dp[i]表示前i个工厂所求的最小费用,则第i个工厂一定会建一个仓库。转移方程为$dp[i]=min(dp[j]+\sum_{k=j}^{i-1}p[k]*(x[i]-x[k]))+c[i]$。

将式子展开,用sump表示p数组的前缀和,sumpx表示p数组*x数组的前缀和。

方程就变成了$dp[i]=min(dp[j] + c[i] + (sumx[i - 1] - sumx[j])*x[i] - (sumpx[i - 1] - sumpx[j]))$

然后设k<j<i时,存在从j转移到i比从k转移到i更优。

则$dp[j] + c[i] + (sumx[i - 1] - sumx[j])*x[i] - (sumpx[i - 1] - sumpx[j])<dp[k] + c[i] + (sumx[i - 1] - sumx[k])*x[i] - (sumpx[i - 1] - sumpx[k])$

移项展开可以得到$dp[j] + sumpx[j] - (dp[k] + sumpd[k]) < (sump[j] - sump[k])*x[i]$

设$f[i]=dp[i]+sumpx[i]$,$T[i]=sump[i]$。

则上式变成$(f[j]-f[k])/(T[j]-T[k])<x[i]$。这就是经典的斜率方程

在每次求dp[i]时我们已经得出了dp[j]和dp[k],则可以得到二维坐标(T[j],f[j]),(T[k],f[k])。

会发现,如果还存在一个点y,y<k,且$(f[k]-f[y])/(T[k]-T[y])>=x[i]$,则k点可以直接被pass掉,在二维坐标中,就是维护一个下凸包点集。

这样就可以使得每次最优转移点可以O(1)得到,程序复杂度为O(n)。

 1 #include<bits/stdc++.h>
 2 #define lson l,mid,i<<1
 3 #define rson mid+1,r,i<<1|1
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 1e6 + 10;
 7 ll c[maxn], x[maxn], p[maxn];
 8 ll sump[maxn];
 9 ll sumpx[maxn];
10 ll dp[maxn];
11 ll q[maxn];
12 ll check1(int j, int k) {
13     return dp[j] + sumpx[j] - dp[k] - sumpx[k];
14 }
15 ll check2(int j, int k) {
16     return sump[j] - sump[k];
17 }
18 int main() {
19     int n;
20     scanf("%d", &n);
21     for (int i = 1; i <= n; i++)
22         scanf("%lld%lld%lld", &x[i], &p[i], &c[i]);
23     for (int i = 1; i <= n; i++)
24         sump[i] = sump[i - 1] + p[i], sumpx[i] = sumpx[i - 1] + p[i] * x[i];
25     int l = 1, r = 1;
26     q[l] = 0;
27     for (int i = 1; i <= n; i++) {
28         while (l < r&&check1(q[l + 1], q[l]) <= x[i] * check2(q[l + 1], q[l]))
29             l++;
30         dp[i] = dp[q[l]] + c[i] + (sump[i - 1] - sump[q[l]])*x[i] - (sumpx[i - 1] - sumpx[q[l]]);
31         while (l < r&&check1(q[r], q[r - 1])*check2(i, q[r]) >= check1(i, q[r])*check2(q[r], q[r - 1]))
32             r--;
33         q[++r] = i;
34     }
35     printf("%lld\n", dp[n]);
36     return 0;
37 }

原文地址:https://www.cnblogs.com/sainsist/p/11130188.html

时间: 2024-10-09 12:02:57

[Bzoj1096][ZJOI2007]仓库建设(斜率优化)的相关文章

[BZOJ1096] [ZJOI2007] 仓库建设 (斜率优化dp)

Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏.由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci.对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏

bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏.由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci.对

BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp

1096: [ZJOI2007]仓库建设 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场

【BZOJ-1096】仓库建设 斜率优化DP

1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Status][Discuss] Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先

P2120 [ZJOI2007]仓库建设 斜率优化dp

好题,这题是我理解的第一道斜率优化dp,自然要写一发题解.首先我们要写出普通的表达式,然后先用前缀和优化.然后呢?我们观察发现,x[i]是递增,而我们发现的斜率也是需要是递增的,然后就维护一个单调递增就行了. 放一个证明题解. 设f[i]表示在i点建仓库的最小费用,易得方程:f[i]=min(f[j]+(x[i]-x[j+1])*p[j+1]+(x[i]-x[j+1])*p[j+2]...) =min(f[j]+c[i]+x[i]*(p[j+1..i])-(x[j+1]*p[j+1]+...+x

BZOJ 1096 ZJOI2007 仓库建设 斜率优化

题目大意:给定n个厂房,在其中一些建仓库,一个点如果没有仓库就要把仓库运到右侧的仓库中,求最小花销 很简单的斜率优化--之前刷斜率优化的时候怎么居然把这道题漏了 令f[i]为在i点建厂使i之前的货物全部安置的最小花销 则有 公式编辑器就是爽啊~ 令sump[i]为p[i]的前缀和 令sumxp[i]为p[i]*x[i]的前缀和 化简有 f[j] + sumxp[j] = x[i]*sump[j] + sumxp[i] - x[i]*sump[i] - C[i] + f[i] 其中 X[j]=su

[ZJOI2007]仓库建设(斜率优化)

L公司有N个工厂,由高到底分布在一座山上. 工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用. 突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏. 由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci. 对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外

【bzoj1096】仓库建设——斜率优化dp

题目链接 我们用sum[i]表示前i个工厂的产品数之和,b[i]表示x[i]*p[i]的前缀和,因此第j+1~i个工厂的产品运到第i个工厂的代价就是 (sum[i]-sum[j])*x[i]-(b[i]-b[j])+ci[i] 最后f[i]的状态转移方程即为: f[i]=f[j]+(sum[i]-sum[j])*xi[i]-(b[i]-b[j])+ci[i] 斜率式的推导过程就不写了,最后可以化成: (f[j]+b[j]-f[k]-b[k])/(sum[j]-sum[k])<xi[i]-ci[i

bzoj 1096: [ZJOI2007]仓库建设 斜率優化

1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2242  Solved: 925[Submit][Status] Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工