BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp
来源:互联网 发布:java图片保存到服务器 编辑:程序博客网 时间:2024/06/06 03:00
点击打开链接
题意:
有个斜坡,有n个仓库,每个仓库里面都有一些物品,物品数目为p,仓库位置为x,修缮仓库需要的费用为c,现在下雨了,之后修缮的仓库才能放东西,别的地方的仓库要运东西过来,但是只能往比它地势低的运,问所有物品得到保障的最小代价。
思路一: 参考:http://www.cnblogs.com/lidaxin/p/5118045.html
斜率优化+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]
其中定义sumpx[]表示p*X的前缀和,sump表示p的前缀和。
设y(j)=f[j]+sumpx[j],a(i)=X[i],x(j)=sump[j],则有
f[i]=(min p = y(j)-a(i)*x(j)) +C[i]-sumpx[i]+X[i]*sump[i]
括号中的式子可以看作一条直线,其中a(i)为i下的常数,x(j)与y(j)都可以在常数时间下确定,而且x与直线斜率(a[i])都是单调递增的,如果以x y建立坐标轴的话,则问题变成已知一条直线的斜率和一堆点,求y轴上的最小截距。
可以通过维护一个下凸包完成,构造一个单调队列,对应该斜率下的直线,从队首维护最优性(p的大小),从队尾维护凸包。
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]
答案就是 q[R]-sumpx[i]; 因为f[i]=now.y-sumpx[i];
代码一:
#include <bits/stdc++.h>using namespace std;typedef long long ll;#define mem(a) memset(a,0,sizeof(a))#define mp(x,y) make_pair(x,y)const int maxn = 1e6+10;const int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}//////////////////////////////////////////////////////////////////////////ll n,x[maxn],p[maxn],C[maxn],sump[maxn],sumpx[maxn];struct node{ll x,y;}now,q[maxn];ll cross(node A,node B,node C){return (B.x-A.x)*(C.y-A.y) - (C.x-A.x)*(B.y-A.y);}int main(){n = read();for(int i=1; i<=n; i++){x[i]=read(),p[i]=read(),C[i]=read();sump[i] = sump[i-1]+p[i];sumpx[i] = sumpx[i-1]+p[i]*x[i];}ll L=0,R=0;for(int i=1; i<=n; i++){while(L<R && q[L].y-x[i]*q[L].x > q[L+1].y-x[i]*q[L+1].x) L++;now.x = sump[i];now.y = q[L].y - x[i]*q[L].x + x[i]*sump[i] + C[i];while(L<R && cross(q[R-1],q[R],now)<0) R--;q[++R] = now;}cout << q[R].y-sumpx[n] << endl; //f[i]=now.y-sumpx[i]; return 0;}
思路二:
f[i]=min{ (f[j]+sumpx[j])-(X[i]*p[j]) }+C[i]-sumpx[i]+X[i]*sump[i]
若有两个决策j和k且j>k,若决策j优于决策k,则有
f[j]-f[k]+sumpx[j]-sumpx[k]<(sump[j]-sump[k])*X[i]
根据斜率判断决策哪个更优。
#include <bits/stdc++.h>using namespace std;typedef long long ll;#define mem(a) memset(a,0,sizeof(a))#define mp(x,y) make_pair(x,y)const int maxn = 1e6+10;const int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}//////////////////////////////////////////////////////////////////////////ll n,x[maxn],p[maxn],c[maxn],sump[maxn],sumpx[maxn],q[maxn],f[maxn];double slope(int j, int k){return (f[j]-f[k]+sumpx[j]-sumpx[k]) / (1.0*(sump[j]-sump[k]));}int main(){n = read();for(int i=1; i<=n; i++){x[i] = read(), p[i] = read(), c[i] = read();sump[i] = sump[i-1]+p[i];sumpx[i] = sumpx[i-1]+p[i]*x[i];}int L=0,R=0;for(int i=1; i<=n; i++){while(L<R && slope(q[L+1],q[L]) <= x[i]) L++;int j = q[L];f[i] = f[j] + (sump[i]-sump[j])*x[i] - (sumpx[i]-sumpx[j]) + c[i];while(L<R && slope(i,q[R])<=slope(q[R],q[R-1])) R--;q[++R] = i;}cout << f[n] << endl; return 0;}
- bzoj 1096: [ZJOI2007]仓库建设 斜率优化+:DP
- [BZOJ]1096: [ZJOI2007]仓库建设 斜率优化DP
- 【BZOJ】1096 [ZJOI2007]仓库建设 dp+斜率优化
- BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp
- [BZOJ 1096][ZJOI2007]仓库建设:DP斜率优化
- 【斜率DP】【bzoj 1096】: [ZJOI2007]仓库建设
- BZOJ 斜率优化 1096: [ZJOI2007]仓库建设
- BZOJ 1096 ZJOI2007 仓库建设 斜率优化
- BZOJ 1096: [ZJOI2007]仓库建设(斜率优化)
- BZOJ 1096: [ZJOI2007]仓库建设 斜率优化
- BZOJ 1096: [ZJOI2007]仓库建设 斜率优化
- 【1096】【ZJOI2007】仓库建设 斜率优化DP
- bzoj 1096: [ZJOI2007]仓库建设(斜率DP)
- BZOJ 1096 [ZJOI2007]仓库建设 动态规划+斜率优化
- 【ZJOI2007】【斜率优化DP】仓库建设
- [BZOJ1096][ZJOI2007][DP][斜率优化]仓库建设
- bzoj1096: [ZJOI2007]仓库建设 斜率优化DP
- [BZOJ1096]ZJOI2007仓库建设|斜率优化DP
- Maven学习(1)-----概念,作用详解,配置
- 我的新玩具-AppleScript(三)
- CS231n-02-Linear Classification
- 救护车
- opencv之cvCopy()和cvCloneImage()的区别
- BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp
- 一个简单的JAVA五子棋
- UVa-11038 How Many O's? (整数区间分解)
- 运算符与表达式
- [notes] javaScript notes
- 我的新玩具-AppleScript(四)
- 最大公约数的欧几里德算法
- MySQL优化
- Codeforces 768B Code For 1 线段树思想