三分 & P2571传送带

还记得二分吗…

何为二分?二分就是取中间值 mid 比较 f(mid) 和目标值的大小, 舍去 Lmidmid +1R 中的其中一个区间 不断收敛得到答案.

当然也有实数域上的二分, 只是要注意退出条件是 R - L < eps .

何为三分

那么如果问题转化成抛物线上求最值, 二分的正确性就不存在了, 这时候就需要三分.

三分有一个 LmidRmid , 若 Lmid 的答案更劣, 则舍去区间 LLmid . 以此类推.

如图所示:

 

如何三分

例: 求开口向下抛物线最高点 ( 凸包

double lmid=l,rmid=r;
while(rmid-lmid>eps){
  double temp=(r-l)/3,t1,t2;
  lmid=l+temp;rmid=l+temp*2;
  t1=calc(lmid);t2=calc(rmid);
  if(t1<t2)l=lmid;
  else r=rmid;
}
return calc(l);

P2571传送带

题意简述

一个平面, 有线段 AB 和线段 CD , 已知人在线段 AB 上速度为 p , 在线段 CD 上速度为 q , 在其他地方的速度为 r , 求 AD 的最短时间.

分析

本质就是在两条线段上各选一个点, 使时间最短, 明显这是个有两个自变量的二次函数 ( 雾

一层三分很明显不行, 因为另一个点不确定, 没办法计算函数值 f(x) 怎么办?

三分套三分

如下图. 形象点理解就是在一层三分中算函数值时套用另一层三分.

 

细节

不是每一层三分都必定会进去计算的. 如果当前三分的定义域本来就很窄 (例: 线段两端点重合) , 则需再调用一次函数计算函数值. 否则将返回 0 .

#include<stdio.h>
#include<math.h>
const double eps=0.0000001;
double ax,ay,bx,by,cx,cy,dx,dy,p,q,r,lpx,lpy,rpx,rpy,lqx,lqy,rqx,rqy;
double lx,ly,rx,ry,t1,t2;
inline double calc(double X1,double Y1,double X2,double Y2){
	double dis1=sqrt((X1-ax)*(X1-ax)+(Y1-ay)*(Y1-ay)),dis2=sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2)),dis3=sqrt((X2-dx)*(X2-dx)+(Y2-dy)*(Y2-dy));
	return dis1/p+dis2/r+dis3/q;
}
inline double solve(double x,double y){
	lqx=cx;lqy=cy;rqx=dx;rqy=dy;
	double t1,t2,lx=lqx,rx=rqx,ly=lqy,ry=rqy;
	while(fabs(rqx-lqx)>eps||fabs(rqy-lqy)>eps){
		double tx=(rqx-lqx)/3,ty=(rqy-lqy)/3;
		lx=lqx+tx;ly=lqy+ty;rx=lqx+tx*2;ry=lqy+ty*2;
		t1=calc(x,y,lx,ly);t2=calc(x,y,rx,ry);
		if(t1>t2)lqx=lx,lqy=ly;
		else rqx=rx,rqy=ry;
	}
	return calc(x,y,lx,ly);   //
}
int main(){					scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy,&p,&q,&r);
	lpx=ax;lpy=ay;rpx=bx;rpy=by;lqx=cx;lqy=cy;rqx=dx;rqy=dy;
	while(fabs(rpx-lpx)>eps||fabs(rpy-lpy)>eps){
		double tx=(rpx-lpx)/3,ty=(rpy-lpy)/3;
		lx=lpx+tx;ly=lpy+ty;rx=lpx+tx*2;ry=lpy+ty*2;
		t1=solve(lx,ly);t2=solve(rx,ry);
		if(t1>t2)lpx=lx,lpy=ly;
		else rpx=rx,rpy=ry;
	}
	printf("%.2lf",solve(lx,ly)); //
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值