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

f[i]=min{ f[j]+p[j+1](x[i]-x[j+1])+p[j+2]*(x[i]-x[j+2]+…p[i](x[i]-x[i]))+C[i] }
=min{ f[j]-(sumpx[i]-sumpx[j])+(sump[i]-sump[j])*x[i] +C[i]}
=min{ (f[j]+sumpx[j])-(X[i]*p[j]) }+C[i]-sumpx[i]+X[i]*sump[i]

f[i]=(min p = y(j)-a(i)*x(j)) +C[i]-sumpx[i]+X[i]*sump[i]

while(L<R && q[L].y-q[L].x*X[i] >= q[L+1].y-q[L+1].x*X[i]) L++;  根据当前直线计算p 维护队首的最优性
while(L<R && cross(q[R-1],q[R],now)<=0) R--;                 //维护与插入当前点, 将不在凸包上的点删去，保证最优
q[++R]=now;

now.x=sump[i];                                                 //计算当前点
now.y=q[L].y-q[L].x*X[i]+C[i]+X[i]*sump[i];   

也就是	y[i] = f[i]+sumpx[i]
= {min{(f[j]+sumpx[j])-sump[j]*X[i])}+X[i]*sump[i]+C[i]-sumpx[i]} + sumpx[i]
= y[j]-sump[j]*X[i] + C[i] + X[i]*sump[i]

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 #define mem(a) memset(a,0,sizeof(a))
5 #define mp(x,y) make_pair(x,y)
6 const int maxn = 1e6+10;
7 const int INF = 0x3f3f3f3f;
8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16
17 ll n,x[maxn],p[maxn],C[maxn],sump[maxn],sumpx[maxn];
18 struct node{
19     ll x,y;
20 }now,q[maxn];
21
22 ll cross(node A,node B,node C){
23     return (B.x-A.x)*(C.y-A.y) - (C.x-A.x)*(B.y-A.y);
24 }
25
26 int main(){
28     for(int i=1; i<=n; i++){
30         sump[i] = sump[i-1]+p[i];
31         sumpx[i] = sumpx[i-1]+p[i]*x[i];
32     }
33
34     ll L=0,R=0;
35     for(int i=1; i<=n; i++){
36         while(L<R && q[L].y-x[i]*q[L].x > q[L+1].y-x[i]*q[L+1].x) L++;
37         now.x = sump[i];
38         now.y = q[L].y - x[i]*q[L].x + x[i]*sump[i] + C[i];
39         while(L<R && cross(q[R-1],q[R],now)<0) R--;
40         q[++R] = now;
41     }
42
43     cout << q[R].y-sumpx[n] << endl; //f[i]=now.y-sumpx[i];
44
45     return 0;
46 }

f[i]=min{ (f[j]+sumpx[j])-(X[i]*p[j]) }+C[i]-sumpx[i]+X[i]*sump[i]

f[j]-f[k]+sumpx[j]-sumpx[k]<(sump[j]-sump[k])*X[i]

 1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 #define mem(a) memset(a,0,sizeof(a))
5 #define mp(x,y) make_pair(x,y)
6 const int maxn = 1e6+10;
7 const int INF = 0x3f3f3f3f;
8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16
17 ll n,x[maxn],p[maxn],c[maxn],sump[maxn],sumpx[maxn],q[maxn],f[maxn];
18
19 double slope(int j, int k){
20     return (f[j]-f[k]+sumpx[j]-sumpx[k]) / (1.0*(sump[j]-sump[k]));
21 }
22
23 int main(){
25     for(int i=1; i<=n; i++){
27         sump[i] = sump[i-1]+p[i];
28         sumpx[i] = sumpx[i-1]+p[i]*x[i];
29     }
30
31     int L=0,R=0;
32     for(int i=1; i<=n; i++){
33         while(L<R && slope(q[L+1],q[L]) <= x[i]) L++;
34         int j = q[L];
35         f[i] = f[j] + (sump[i]-sump[j])*x[i] - (sumpx[i]-sumpx[j]) + c[i];
36         while(L<R && slope(i,q[R])<=slope(q[R],q[R-1])) R--;
37         q[++R] = i;
38     }
39
40     cout << f[n] << endl;
41
42     return 0;
43 }

posted @ 2017-02-22 22:33  _yxg123  阅读(35)  评论(0编辑  收藏