1. 程式人生 > >【bzoj1096】倉庫建設——斜率優化dp

【bzoj1096】倉庫建設——斜率優化dp

getch ron con span bdd nss typedef a20 family

題目鏈接

我們用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](k<j<i)

//然而剛開始最後的那個加號寫成乘號導致WA了兩次,要註意隊列的q[0]=0(不是1!!!),還是要細心吧。

代碼:

技術分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef long long LL;
 5 const int maxn=1000010;
 6 using namespace std;
 7 LL xi[maxn],pi[maxn],ci[maxn],sum[maxn],b[maxn],f[maxn],q[maxn];
 8 inline LL read()
 9 {
10     LL anss=0,f=1;char c=getchar();
11 while(c<0||c>9){if(c==-)f=-1;c=getchar();} 12 while(c>=0&&c<=9){anss=anss*10+c-48;c=getchar();} 13 return anss*f; 14 } 15 inline double cal(LL a,LL bb) 16 { 17 return 1.0*(f[a]+b[a]-f[bb]-b[bb])/(sum[a]-sum[bb]); 18 } 19 int main() 20 { 21 int
n; 22 n=read(); 23 sum[0]=0;b[0]=0; 24 for(int i=1;i<=n;i++){ 25 xi[i]=read();pi[i]=read();ci[i]=read(); 26 sum[i]=sum[i-1]+pi[i]; 27 b[i]=b[i-1]+xi[i]*pi[i]; 28 } 29 int h=0,t=1;q[0]=0;f[0]=0; 30 for(int i=1;i<=n;i++){ 31 while(h<t-1&&cal(q[h],q[h+1])<xi[i])h++; 32 f[i]=f[q[h]]+(sum[i]-sum[q[h]])*xi[i]-(b[i]-b[q[h]])+ci[i]; 33 while(h<t-1&&cal(q[t-2],q[t-1])>cal(q[t-1],i))t--; 34 q[t++]=i; 35 } 36 printf("%lld",f[n]); 37 return 0; 38 }
bzoj1096

【bzoj1096】倉庫建設——斜率優化dp