[题解] P2120 [ZJOI2007]仓库建设
作者:互联网
[题解] P2120 [ZJOI2007]仓库建设
洛谷题目链接
首先考虑用动态规划
f_ifi 表示从第 11 个到第 ii 个位置 (第 ii 个位置修建仓库) 的代价
sum_isumi 表示从第 11 个到第 ii 个位置的成品总和
dis_idisi 表示到第 ii 个位置到到第 nn 个位置的距离
s_isi 表示从 11 个到第 ii 个位置所有成品运输到第 nn 个位置的代价
可以列出转移方程
f_i=min\{f_j+s_i-s_j-(sum_i-sum_j)*dis_i\}_{0 \le j \le i-1}+c_ifi=min{fj+si−sj−(sumi−sumj)∗disi}0≤j≤i−1+ci
其中 s_i-s_j-(sum_i-sum_j)*dis_isi−sj−(sumi−sumj)∗disi 表示从第 j+1j+1 个到第 ii 个位置所有成品运到仓库 ii 的代价
代码如下
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+7;
int n,x[N],p[N],c[N],sum[N],s[N],f[N];
int Q[N],l=1,r=1;
int X(int x){return Q[x]==0?0:-sum[Q[x]];}
int Y(int x){return Q[x]==0?0:f[Q[x]]+s[Q[x]+1];}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d%d",&x[i],&p[i],&c[i]);
for(int i=1;i<=n;i++)x[i]=x[n]-x[i],sum[i]=sum[i-1]+p[i],s[i]=s[i-1]+x[i]*p[i];
for(int i=1;i<=n;i++){
f[i]=1e9+7;
for(int j=0;j<i;j++)f[i]=min(f[i],f[j]+s[i]-s[j]-(sum[i]-sum[j])*x[i]+c[i]);
}
printf("%d",f[n]);
return 0;
}
但是显然这方法复杂度是 O(n^2)O(n2) 无法通过此题
观察转移方程,可以发现可以使用斜率优化
f_i=f_j+s_i-s_j-(sum_i-sum_j)*dis_i+c_ifi=fj+si−sj−(sumi−sumj)∗disi+ci
f_i=f_j+s_i-s_j-sum_i*dis_i+sum_j*dis_i+c_ifi=fj+si−sj−sumi∗disi+sumj∗disi+ci
移项得到
f_j-s_j=-sum_j*dis_i+f_i-s_i+sum_i*dis_i-c_ifj−sj=−sumj∗disi+fi−si+sumi∗disi−ci
x: -sum_jx:−sumj
y: f_j-s_jy:fj−sj
k: dis_ik:disi
b: f_i-s_i+sum_i*dis_i-c_ib:fi−si+sumi∗disi−ci
其中 xx 单调不增,可以用斜率优化 O(n)O(n) 解决
代码如下
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std;
const int N=1e6+7;
int n,x[N],p[N],c[N],sum[N],s[N],f[N];
int Q[N],l=1,r=1;
int X(int x){return Q[x]==0?0:-sum[Q[x]];}
int Y(int x){return Q[x]==0?0:f[Q[x]]-s[Q[x]];}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&x[i],&p[i],&c[i]);
for(int i=1;i<=n;i++)x[i]=x[n]-x[i],sum[i]=sum[i-1]+p[i],s[i]=s[i-1]+x[i]*p[i];
for(int i=1;i<=n;i++){
while(l<r&&((X(l)-X(l+1))*x[i]<=(Y(l)-Y(l+1))))++l;
int j=Q[l];
f[i]=f[j]+s[i]-s[j]-sum[i]*x[i]+sum[j]*x[i]+c[i],Q[++r]=i;
while(l+1<r&&(Y(r-2)-Y(r-1))*(X(r-1)-X(r))<=(Y(r-1)-Y(r))*(X(r-2)-X(r-1)))Q[r-1]=Q[r],--r;
}
printf("%lld",f[n]);
return 0;
}
标签:ii,int,题解,sum,P2120,sumj,disi,ZJOI2007,dis 来源: https://blog.csdn.net/qq_46636543/article/details/113079111