题目
分析
恩NOIP快来了,作为一个没写过三分的弱菜,赶紧找一道三分题写一写,免得到时候写不出来。
三分法
对于一个上凸函数,若对于Ax,Bx(Ax < Bx),有Ay < By则峰顶必然在(Ax,+∞);若有Ay < By则峰顶必然在(-∞,Bx)中;若有Ay=By则峰顶必然在[Ax,Bx]中。
下凸函数同理。
回到这题,这题要我们在两条直线上分别求两个点,那么我们假设直线AB上取的点已经固定,那么在直线CD上取的点和A到D的距离一定是一个下凸函数(傻逼的我一开始还以为是上凸函数),那么我们就可以用三分法来求这个点。
但现在AB上的点不固定怎么办呢?同理我们也可以用三分法来求这个点,也就是所说的三分套三分。
一开始zz了,算时间居然用的是距离/速度~~感觉NOIP药丸啊!!!
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const double eps=1e-12;
struct pot{double x,y;}A,B,C,D;;
double P,Q,R;
double dis(pot a,pot b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double check(pot mid)
{
pot l=C,r=D;
while (dis(l,r)>=eps)
{
double w1=(r.x-l.x)/3,w2=(r.y-l.y)/3;
pot mid1,mid2;
mid1.x=l.x+w1;mid1.y=l.y+w2;
mid2.x=r.x-w1;mid2.y=r.y-w2;
double ans1=dis(A,mid)/P+dis(mid,mid1)/R+dis(mid1,D)/Q,ans2=dis(A,mid)/P+dis(mid,mid2)/R+dis(mid2,D)/Q;
if (ans1>=ans2) l=mid1;
if (ans1<=ans2) r=mid2;
}
return dis(A,mid)/P+dis(mid,l)/R+dis(l,D)/Q;
}
int main()
{
scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
scanf("%lf%lf%lf%lf",&C.x,&C.y,&D.x,&D.y);
scanf("%lf%lf%lf",&P,&Q,&R);
pot l=A,r=B;
while (dis(l,r)>=eps)
{
double w1=(r.x-l.x)/3,w2=(r.y-l.y)/3;
pot mid1,mid2;
mid1.x=l.x+w1;mid1.y=l.y+w2;
mid2.x=r.x-w1;mid2.y=r.y-w2;
double ans1=check(mid1),ans2=check(mid2);
if (ans1>=ans2) l=mid1;
if (ans1<=ans2) r=mid2;
}
printf("%.2lf",check(l));
return 0;
}