[斜率优化DP] BZOJ1096: [ZJOI2007]仓库建设
来源:互联网 发布:c语言数据类型字节数 编辑:程序博客网 时间:2024/06/01 08:08
题意
有N个工厂按编号顺序排成一条直线,第1个工厂到第i个工厂的距离为dis[i], 第i个工厂一开始堆积着p[i]个货物,现在要紧急把所有货物装进仓库里。在第i个工厂建仓库需要c[i]的代价,对于没有建立仓库的工厂,其货物应被运往其他的仓库进行储藏,且只能往编号大仓库的运,一件货物运送1个单位距离的代价是1。求把所有货物装进仓库的最小代价。
(n<=100000)
题解
显然是DP,要用到斜率优化。
很容易设计出O(n^2)的算法,f[i]表示前i个工厂送完的最优解。
转移方程:f[i]=c[i]+min{ f[j]+
先把方程进行整理:
f[i]=c[i]+min{ f[j]+
写成前缀和的形式,设sum_p[i]为 p[i]的前缀和,sum_pd[i]为p[i]*dis[i]的前缀和。
f[i]=c[i]+min{ f[j]+dis[i]*( sum_p[i] - sum_p[j] )+ sum_pd[i] - sum_pd[j] }
f[i]=c[i] + dis[i]*sum_p[i] + sum_pd[i] + min{ f[j] - sum_pd[j] - dis[i]*sum_p[j] }
我们现在只需关注min中的内容,设 M = f[j] - sum_pd[j] - dis[i]*sum_p[j]
整理得 dis[i]*sum_p[j] + M = f[j] - sum_pd[j]
直线的方程 k * x + b = y
我们把一个决策j转化成了点(sum_p[j], f[j] - sum_pd[j])
那么找当前状态i的最小的M转化为:将一条斜率为dis[i]的直线从下向上移动,碰到第一个点就是最优决策。因为这时直线的截距b最小,对应M最小。
显然能成为最优决策的点一定是凸包(下凸壳)上的点。
因为点的x坐标有单调性,新点只在末端插入,所以可以用一个栈来维护凸壳(Graham)。
又因为斜率dis[i]是单调的,所以决策点也是单调的,即随着i的增加在凸壳上往右动。所以找最优点时只需记一个决策指针在栈中一步步推就行了。
因为有决策单调和x单调这两个很好的性质,复杂度可优化为O(n)。
#include<cstdio>#include<algorithm>typedef long long LL;using namespace std;const int maxn=1000005;int n;LL f[maxn],d[maxn],p[maxn],c[maxn],sum_p[maxn],sum_pd[maxn];struct Point{ LL x,y; Point(LL x=0,LL y=0):x(x),y(y){}} que[maxn];typedef Point Vector;Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y); }LL Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x; }LL getM(int now,int k){ return que[now].y-que[now].x*k;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lld%lld%lld",&d[i],&p[i],&c[i]); sum_p[i]=sum_p[i-1]+p[i]; sum_pd[i]=sum_pd[i-1]+p[i]*d[i]; } while(n&&!p[n]) n--; que[0].x=que[0].y=0; int head=0,tail=0; for(int i=1;i<=n;i++){ while(head<tail&&getM(head,d[i])>getM(head+1,d[i])) head++; f[i]=getM(head,d[i])+c[i]+d[i]*sum_p[i]-sum_pd[i]; Point now(sum_p[i],f[i]+sum_pd[i]); while(tail>0&&Cross(que[tail]-que[tail-1],now-que[tail])<0) tail--; que[++tail]=now; if(head>tail) head=tail; } printf("%lld\n",f[n]); return 0;}
- [BZOJ1096][ZJOI2007][DP][斜率优化]仓库建设
- bzoj1096: [ZJOI2007]仓库建设 斜率优化DP
- [BZOJ1096]ZJOI2007仓库建设|斜率优化DP
- 【bzoj1096】[ZJOI2007]仓库建设 斜率优化DP
- 【bzoj1096】【ZJOI2007】【仓库建设】【斜率优化dp】
- BZOJ1096: [ZJOI2007]仓库建设 斜率优化DP
- [斜率优化DP] BZOJ1096: [ZJOI2007]仓库建设
- 【斜率优化DP】BZOJ1096 [ZJOI2007]仓库建设
- bzoj1096[ZJOI2007]仓库建设 斜率优化dp
- BZOJ1096(ZJOI2007)仓库建设--斜率优化DP
- bzoj1096 [ZJOI2007]仓库建设 斜率优化dp
- BZOJ1096 [ZJOI2007]仓库建设(斜率优化dp)
- [BZOJ1096][ZJOI2007]仓库建设(斜率优化dp)
- 【bzoj1096】【ZJOI2007】仓库建设(dp+前缀和+斜率优化)
- 【BZOJ1096】[ZJOI2007]仓库建设【斜率优化】
- bzoj1096 [ZJOI2007]仓库建设(斜率优化)
- 【BZOJ1096】仓库建设,斜率优化DP练习
- 【bzoj1096】仓库建设 斜率优化dp
- android开发处理硬件访问设备权限问题
- Solr分面搜索示例
- 1091. Acute Stroke (30) PAT甲级
- Javascript高级编程读书笔记一
- TCP-IP协议族(二) HTTP报文头解析
- [斜率优化DP] BZOJ1096: [ZJOI2007]仓库建设
- wireshark简单抓包
- thinkphp实现对MySQL数据库实现备份功能
- 解析Javascript事件冒泡机制
- 寒假篇40
- NodeJS之重构Express路由
- java中的异或
- Tornado、Bottle以及Flask
- 挂起进程和进程的阻塞和挂起的区别