斜率优化dp(POJ1180 Uva1451)
2014-03-27 14:48
411 查看
学这个斜率优化dp却找到这个真心容易出错的题目,其中要从n倒过来到1的确实没有想到,另外斜率优化dp的算法一开始看网上各种大牛博客自以为懂了,最后才发现是错了。
不过觉得看那些博客中都是用文字来描述,还是应该用画图来表示更容易让人明白,不过时间不太够,且网上该题解法到处都是,就不累赘了。
代码才20几行真爽
更为详细的描述参见:
《浅谈数形结合思想在信息学竞赛中的应用》 周源
POJ 1180
稍微加深自己的印象
一般来说,斜率优化是从一些特殊数据的一些类似斜率的性质上找出其单调性。对于普通动态规划方程
例如 poj1180(不考虑反向来讨论)
F[i]=min(F[j]+(s+sumt[i]-sumt[j])*sumf[i])
因此我们可以考虑
在i之前
在k<j<i时,考虑使
F[j]+(s+sumt[i]-sumt[j])*sumf[i]<F[k]+(s+sumt[i]-sumf[k])*sumf[i]
化简后可得到
(F[j]-F[k])/(sumt[j]-sumt[k])<sumf[i]
可以类比斜率,如果满足这个条件,那么决策j就比决策k更好,因此我们令
ratio(k,j)=(F[j]-F[k])/(sumt[j]-sumt[k])
当满足ratio(k,j)<sumf[i]则有j好于k
而sumf[i]又是递增的,可以考虑单调队列。
那应该用一个怎样的单调队列来维护最优值呢?
什么值是不需要的?
当ratio(l,k)>ratio(k,j) (l<k<j)时
如果sumf[i]<ratio(k,j),则这些现在都不会是最优决策
如果ratio(k,j)<sumf[i]<ratio(l,k),则j优于k,l优于k
如果ratio(l,k)<sumf[i],则j最优
因此可以看出k是不需要的
因此可以将k节点删去,最后得到的单调队列则有保证ratio递增
关于单调队列具体操作:
1.将队列中头部满足ratio(head,head+1)<sumf[i]的所有删去,因为sumf是递增的,故此后永远满足head比head+1差,所以可以删去到ratio(head,head+1)>sumf[i],此时head即最优决策。
2.计算出新的ratio(tail,i)不断从尾部往前删除直到ratio(tail,i)>ratio(tail,tail-1).然后将i插入尾部即可
View Code
不过觉得看那些博客中都是用文字来描述,还是应该用画图来表示更容易让人明白,不过时间不太够,且网上该题解法到处都是,就不累赘了。
代码才20几行真爽
更为详细的描述参见:
《浅谈数形结合思想在信息学竞赛中的应用》 周源
POJ 1180
稍微加深自己的印象
一般来说,斜率优化是从一些特殊数据的一些类似斜率的性质上找出其单调性。对于普通动态规划方程
例如 poj1180(不考虑反向来讨论)
F[i]=min(F[j]+(s+sumt[i]-sumt[j])*sumf[i])
因此我们可以考虑
在i之前
在k<j<i时,考虑使
F[j]+(s+sumt[i]-sumt[j])*sumf[i]<F[k]+(s+sumt[i]-sumf[k])*sumf[i]
化简后可得到
(F[j]-F[k])/(sumt[j]-sumt[k])<sumf[i]
可以类比斜率,如果满足这个条件,那么决策j就比决策k更好,因此我们令
ratio(k,j)=(F[j]-F[k])/(sumt[j]-sumt[k])
当满足ratio(k,j)<sumf[i]则有j好于k
而sumf[i]又是递增的,可以考虑单调队列。
那应该用一个怎样的单调队列来维护最优值呢?
什么值是不需要的?
当ratio(l,k)>ratio(k,j) (l<k<j)时
如果sumf[i]<ratio(k,j),则这些现在都不会是最优决策
如果ratio(k,j)<sumf[i]<ratio(l,k),则j优于k,l优于k
如果ratio(l,k)<sumf[i],则j最优
因此可以看出k是不需要的
因此可以将k节点删去,最后得到的单调队列则有保证ratio递增
关于单调队列具体操作:
1.将队列中头部满足ratio(head,head+1)<sumf[i]的所有删去,因为sumf是递增的,故此后永远满足head比head+1差,所以可以删去到ratio(head,head+1)>sumf[i],此时head即最优决策。
2.计算出新的ratio(tail,i)不断从尾部往前删除直到ratio(tail,i)>ratio(tail,tail-1).然后将i插入尾部即可
#include <cstdio> #include <cmath> #define eps 1e-13 int ansl,ansr,n,l,d[100005],sum[100005]; double ans; bool equ(double x,double y){ return(fabs(x-y)<eps); } inline double ratio(int a,int b){ return((sum[a]-sum[b])*1.0/(a-b)); } int main() { int t; scanf("%d",&t); while(t--){ sum[0]=0; scanf("%d%d",&n,&l); for(int i=1; i<=n; i++){ scanf("%1d",&sum[i]); sum[i]+=sum[i-1]; } ans=0; ansl=0;ansr=l;//注意初始化,可能出现0000000 int g=1,h=0; for(int i=l; i<=n; i++){ while(h>g&&ratio(d[h],i-l)<=ratio(d[h-1],d[h])) h--; d[++h]=i-l; while(g<h&&(ratio(d[g],i)<=ratio(d[g+1],i))) g++; if(ratio(d[g],i)>ans&&!equ(ans,ratio(d[g],i))) { ans=ratio(d[g],i); ansl=d[g]+1; ansr=i; } else if(equ(ans,ratio(d[g],i))&&i-d[g]<ansr-ansl+1){ ansl=d[g]+1; ansr=i; } } printf("%d %d\n",ansl,ansr); } return 0; }
View Code
相关文章推荐
- POJ 1180 斜率优化DP
- POJ - 1180 Batch Scheduling(斜率优化DP)
- POJ 1180 Batch Scheduling (斜率优化DP)
- poj 1180:Batch Scheduling【斜率优化dp】
- Poj1180 Batch Scheduling --- DP的斜率优化
- POJ 1180 Batch Scheduling(斜率优化DP)
- Poj1180 Batch Scheduling --- DP的斜率优化
- poj 1180 斜率优化dp
- poj 1180 Batch Scheduling(斜率优化dp或决策单调)
- poj 1180 Batch Scheduling 斜率优化dp
- poj 1180 斜率优化DP
- POJ-1180 Batch Scheduling 【逆向DP+斜率优化】
- POJ 1180 Batch Scheduling(斜率优化DP)
- 斜率优化DP(POJ1180 && POJ3709)
- poj 1180 斜率优化dp
- poj 1180 Batch Scheduling dp斜率优化
- poj 1180 Batch Scheduling 斜率优化dp
- poj 1180 Batch Scheduling ( 斜率优化DP )
- poj 1180 dp 斜率优化
- poj 3709 K-Anonymous Sequence 斜率优化dp