bzoj1010: [HNOI2008]玩具装箱toy(斜率优化)
2017-10-22 16:17
309 查看
题目传送门
斜率优化拖了好久都没学。。
解法:
%%%
f[i]表示1~i的最小花费。
f[i]=min(f[j]+(sum[i]-sum[j]+i-(j+1)-L)^2) (j<i)
f[i]=min(f[j]+(sum[i]+i-sum[j]-j-1-L)^2) (j<i)
令s[i]=sum[i]+i,L=1+L
则f[i]=min(f[j]+(s[i]-s[j]-L)^2)
1.证明决策单调性
假设j1<j2<i,在状态i处的j2决策不比j1决策差(心里想着淘汰j1),
即要满足:f[j2]+(s[i]-s[j2]-L)^2<f[j1]+(s[i]-s[j1]-L)^2
则对于i后的所有状态t,是否j2也不比就j1差?(术语:证明决策单调性)
即f[j2]+(s[t]-s[j2]-L)^2 < f[j1]+(s[t]-s[j1]-L)^2
容易理解s[t]=s[i]+v
所以得到(1)不等式:f[j2]+(s[i]-s[j2]-L+v)^2<f[j1]+(s[i]-s[j1]-L+v)^2
因为已知(2)不等式:f[j2]+(s[i]-s[j2]-L )^2<f[j1]+(s[i]-s[j1]-L )^2
所以化简(1)不等式:把s[i]-s[j2]-L看成一个整体,v看成一个整体,得到
f[j2]+(s[i]-s[j2]-L )^2 +2*v*(s[i]-s[j2]-L)+v^2 <f[j1]+(s[i]-s[j1]-L )^2+2*v*(s[i]-s[j1]-L)+v^2
比较(2)不等式:
左边多了一部分:2*v*(s[i]-s[j2]-L)+v^2
右边多了一部分:2*v*(s[i]-s[j1]-L)+v^2
所以我们只需要证:
2*v*(s[i]-s[j2]-L)+v^2<=2*v*(s[i]-s[j1]-L)+v^2
即:(s[i]-s[j2]-L) <= (s[i]-s[j1]-L)
即: -s[j2] <= -s[j1]
即:s[j1]<s[j2]这是肯定的,所以得证。
总结:对于当前i:j2比j1好,那么对于t(i<t)来说一样:j2一样比j1好,
所以当前i选择j2,淘汰j1,以后的t也不会在j2存在的时候选择j1,
所以i的时候就可以永久淘汰j1.
2.求斜率方程:
因为f[j2]+(s[i]-s[j2]-L)^2 < f[j1]+(s[i]-s[j1]-L)^2
展开:
f[j2]+(s[i]-L)^2-2*(s[i]-L)s[j2]+s[j2]^2<f[j1]+(s[i]-L)^2-2(s[i]-L)*s[j1]+s[j1]^2
即f[j2]-2*(s[i]-L)s[j2]+s[j2]^2<f[j1]-2(s[i]-L)*s[j1]+s[j1]^2
即f[j2]+s[j2]^2-2*(s[i]-L)s[j2]<=f[j1]+s[j1]^2-2(s[i]-L)*s[j1]
即[ (f[j2]+s[j2]^2)-(f[j1]+s[j1]^2) ] <
2*(s[i]-L)s[j2]-2(s[i]-L)*s[j1]
即[ (f[j2]+s[j2]^2)-(f[j1]+s[j1]^2) ] /(s[j2]-s[j1]) < 2*(s[i]-L)
对于j来说:
制造的点坐标
Y=f[j]+s[j]^2
X=s[j]
我们用队列list在存有意义的决策点,list中相邻两点的斜率递增(队列中的点形成一个下凸壳),而且都
大于2*(s[i]-L),那么队列头对于i来说就是最优决策点。
加入决策i时,令队尾为list[tail],前一个为list[tail-1]
斜率函数slop(点1,点2)
满足: slop(list[tail-1],list[tail]) > slop(list[tail],i) 时,
那么队尾list[tail]在三者(list[tail-1],list[tail],i)对于未来的t绝对不会是最优的策略,所以将
其弹出tail–;
最后遇到了:slop(list[tail-1],list[tail]) <
slop(list[tail],i),保证了队列的相邻两点的斜率递
增所以加入i: list[++tail]=i;
代码实现:
斜率优化拖了好久都没学。。
解法:
%%%
f[i]表示1~i的最小花费。
f[i]=min(f[j]+(sum[i]-sum[j]+i-(j+1)-L)^2) (j<i)
f[i]=min(f[j]+(sum[i]+i-sum[j]-j-1-L)^2) (j<i)
令s[i]=sum[i]+i,L=1+L
则f[i]=min(f[j]+(s[i]-s[j]-L)^2)
1.证明决策单调性
假设j1<j2<i,在状态i处的j2决策不比j1决策差(心里想着淘汰j1),
即要满足:f[j2]+(s[i]-s[j2]-L)^2<f[j1]+(s[i]-s[j1]-L)^2
则对于i后的所有状态t,是否j2也不比就j1差?(术语:证明决策单调性)
即f[j2]+(s[t]-s[j2]-L)^2 < f[j1]+(s[t]-s[j1]-L)^2
容易理解s[t]=s[i]+v
所以得到(1)不等式:f[j2]+(s[i]-s[j2]-L+v)^2<f[j1]+(s[i]-s[j1]-L+v)^2
因为已知(2)不等式:f[j2]+(s[i]-s[j2]-L )^2<f[j1]+(s[i]-s[j1]-L )^2
所以化简(1)不等式:把s[i]-s[j2]-L看成一个整体,v看成一个整体,得到
f[j2]+(s[i]-s[j2]-L )^2 +2*v*(s[i]-s[j2]-L)+v^2 <f[j1]+(s[i]-s[j1]-L )^2+2*v*(s[i]-s[j1]-L)+v^2
比较(2)不等式:
左边多了一部分:2*v*(s[i]-s[j2]-L)+v^2
右边多了一部分:2*v*(s[i]-s[j1]-L)+v^2
所以我们只需要证:
2*v*(s[i]-s[j2]-L)+v^2<=2*v*(s[i]-s[j1]-L)+v^2
即:(s[i]-s[j2]-L) <= (s[i]-s[j1]-L)
即: -s[j2] <= -s[j1]
即:s[j1]<s[j2]这是肯定的,所以得证。
总结:对于当前i:j2比j1好,那么对于t(i<t)来说一样:j2一样比j1好,
所以当前i选择j2,淘汰j1,以后的t也不会在j2存在的时候选择j1,
所以i的时候就可以永久淘汰j1.
2.求斜率方程:
因为f[j2]+(s[i]-s[j2]-L)^2 < f[j1]+(s[i]-s[j1]-L)^2
展开:
f[j2]+(s[i]-L)^2-2*(s[i]-L)s[j2]+s[j2]^2<f[j1]+(s[i]-L)^2-2(s[i]-L)*s[j1]+s[j1]^2
即f[j2]-2*(s[i]-L)s[j2]+s[j2]^2<f[j1]-2(s[i]-L)*s[j1]+s[j1]^2
即f[j2]+s[j2]^2-2*(s[i]-L)s[j2]<=f[j1]+s[j1]^2-2(s[i]-L)*s[j1]
即[ (f[j2]+s[j2]^2)-(f[j1]+s[j1]^2) ] <
2*(s[i]-L)s[j2]-2(s[i]-L)*s[j1]
即[ (f[j2]+s[j2]^2)-(f[j1]+s[j1]^2) ] /(s[j2]-s[j1]) < 2*(s[i]-L)
对于j来说:
制造的点坐标
Y=f[j]+s[j]^2
X=s[j]
我们用队列list在存有意义的决策点,list中相邻两点的斜率递增(队列中的点形成一个下凸壳),而且都
大于2*(s[i]-L),那么队列头对于i来说就是最优决策点。
加入决策i时,令队尾为list[tail],前一个为list[tail-1]
斜率函数slop(点1,点2)
满足: slop(list[tail-1],list[tail]) > slop(list[tail],i) 时,
那么队尾list[tail]在三者(list[tail-1],list[tail],i)对于未来的t绝对不会是最优的策略,所以将
其弹出tail–;
最后遇到了:slop(list[tail-1],list[tail]) <
slop(list[tail],i),保证了队列的相邻两点的斜率递
增所以加入i: list[++tail]=i;
代码实现:
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll s[510000],f[510000]; int list[510000],head,tail; double hh(int y,int x) { //求斜率的东西 return ((f[x]+s[x]*s[x])-(f[y]+s[y]*s[y]))/(s[x]-s[y]); } int main() { ll l; int n;scanf("%d%lld",&n,&l);l++; int sum=0; for(int i=1;i<=n;i++) { ll x;scanf("%lld",&x); sum+=x; s[i]=sum+i; } head=1;tail=1;list[1]=0; for(int i=1;i<=n;i++) { while(head<tail&&hh(list[head],list[head+1])<=(s[i]-l)*2.0) head++; int x=list[head]; f[i]=f[x]+(s[i]-s[x]-l)*(s[i]-s[x]-l); while(head<tail&&hh(list[tail],i)<hh(list[tail-1],list[tail])) tail--; list[++tail]=i; } printf("%lld\n",f ); return 0; }
相关文章推荐
- BZOJ 1010 [HNOI2008]玩具装箱toy(斜率优化)
- 【BZOJ 1010】 [HNOI2008]玩具装箱toy (斜率优化)
- 【bzoj1010】[HNOI2008]玩具装箱toy 斜率优化dp
- bzoj1010[HNOI2008] 玩具装箱toy(带斜率优化学习笔记)
- Bzoj 1010[HNOI2008]玩具装箱toy【斜率优化Dp入门】
- bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
- 【动态规划18】bzoj1010 [HNOI2008]玩具装箱toy(斜率优化)
- _bzoj1010 [HNOI2008]玩具装箱toy【斜率优化dp】
- 【动态规划】【斜率优化】[BZOJ1010][HNOI2008]玩具装箱toy
- BZOJ 1010 [HNOI2008]玩具装箱toy 斜率优化DP
- BZOJ1010: [HNOI2008]玩具装箱toy 斜率优化DP
- bzoj1010: [HNOI2008]玩具装箱toy 斜率优化DP
- BZOJ 1010: [HNOI2008]玩具装箱toy(斜率优化dp)
- 【bzoj1010】【HNOI2008】【玩具装箱toy】【斜率优化】
- bzoj 1010: [HNOI2008]玩具装箱toy 动态规划+斜率优化
- BZOJ 1010 [HNOI2008]玩具装箱toy 斜率优化
- [BZOJ1010][HNOI2008]玩具装箱toy(斜率优化dp)
- bzoj1010 [HNOI2008]玩具装箱toy 斜率优化 DP
- BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)
- BZOJ 1010 [HNOI2008]玩具装箱TOY (dp+斜率优化)