这题一开始看错题了,原来最多的走的距离是它本身走的最短距离+t,之前以为是比两个路长中较小的那个不超过多少。。。就变成了未知数。设最长路长分别为l1,l2
那么如果alan和bob能一直一起走,那么就是最长一起走的路径min(l1,l2)
否则就是一起走到P点,假设cinema到P为x,那么x+dis(P,shop)+dis(shop,house)<=l1; x+dis(P,house)<=l2
那么可以以cinema,shop,house作三个圆,如果3个圆有交集,那么P点就可能在这3个圆的交集中
3个圆有交集,有3中情况
1.两两圆求交点,若有交点落在第三个圆内。
2.小圆包含在中圆中,中圆包含在大圆中
3.小圆在中圆中,小圆公式在大圆中
注意精度,1e-8WA on test 32,1e-10就过了。而且余弦定理要判断是否算出来的值>1.0或<1.0
upadte 2019.2.6---据说acos很容易损失精度,所以我们使用直接传入cosb和sinb进行操作
#include<bits/stdc++.h>
#define maxl 110
#define eps 1e-10
using namespace std;
const double pi=acos(-1.0);
struct point
{
double x,y;
point(double a=0,double b=0)
{
x=a;y=b;
}
point operator + (const point &b)const
{
return point(x+b.x,y+b.y);
}
point operator - (const point &b)const
{
return point(x-b.x,y-b.y);
}
double operator * (const point &b)const
{
return x*b.x+y*b.y;
}
double operator ^ (const point &b)const
{
return x*b.y-y*b.x;
}
void transxy(double sinb,double cosb)
{ //given sinb cosb
double tx=x,ty=y;
x=tx*cosb-ty*sinb;
y=tx*sinb+ty*cosb;
}
void transxy(double b)
{
double tx=x,ty=y;
x=tx*cos(b)-ty*sin(b);
y=tx*sin(b)+ty*cos(b);
}
double get_len()
{
return sqrt(x*x+y*y);
}
}cinema,shop,house,intersec1,intersec2;
struct circle
{
point ctr;
double r;
circle(point a=point(),double radius=0)
{
ctr=a;r=radius;
}
};
double t1,t2,l1,l2,ans;
double get_dist(point &a,point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline void prework()
{
scanf("%lf%lf",&t1,&t2);
scanf("%lf%lf",&cinema.x,&cinema.y);
scanf("%lf%lf",&house.x,&house.y);
scanf("%lf%lf",&shop.x,&shop.y);
l1=get_dist(cinema,shop)+get_dist(shop,house)+t1;
l2=get_dist(cinema,house)+t2;
}
inline bool get_circle_intersec(point a,double ra,point b,double rb)
{
double len=get_dist(a,b);
if(len>ra+rb+eps)
return false;
double cosb=(ra*ra+len*len-rb*rb)/(2*ra*len);
if(cosb<-1.0)
cosb+=eps;
if(cosb>1.0)
cosb-=eps;
double sinb=sqrt(1.0-cosb*cosb);
point vec=b-a;
vec.transxy(sinb,cosb);
double t=(ra/sqrt(vec*vec));
intersec1=a+point(vec.x*t,vec.y*t);
vec=b-a;
vec.transxy(-sinb,cosb);
intersec2=a+point(vec.x*t,vec.y*t);
return true;
}
inline bool cmp(const circle &x,const circle &y)
{
return x.r<y.r;
}
inline bool jug(double x)
{
double r[3];
r[0]=x,r[1]=l1-get_dist(shop,house)-x,r[2]=l2-x;
if(r[0]<=eps || r[1]<=eps || r[2]<=eps)
return false;
circle cir[3];
cir[0]=circle(cinema,r[0]);
cir[1]=circle(shop,r[1]);
cir[2]=circle(house,r[2]);
if(get_circle_intersec(cinema,r[0],shop,r[1]))
{
if(get_dist(intersec1,house)<r[2]+eps)
return true;
if(get_dist(intersec2,house)<r[2]+eps)
return true;
}
if(get_circle_intersec(cinema,r[0],house,r[2]))
{
if(get_dist(intersec1,shop)<r[1]+eps)
return true;
if(get_dist(intersec2,shop)<r[1]+eps)
return true;
}
if(get_circle_intersec(shop,r[1],house,r[2]))
{
if(get_dist(intersec1,cinema)<r[0]+eps)
return true;
if(get_dist(intersec2,cinema)<r[0]+eps)
return true;
}
sort(cir,cir+3,cmp);
if((cir[0].ctr-cir[1].ctr).get_len()+cir[0].r<cir[1].r+eps &&
(cir[0].ctr-cir[2].ctr).get_len()+cir[0].r<cir[2].r+eps)
return true;
if((cir[0].ctr-cir[1].ctr).get_len()+cir[0].r<cir[1].r+eps &&
(cir[1].ctr-cir[2].ctr).get_len()+cir[1].r<cir[2].r+eps)
return true;
return false;
}
inline void mainwork()
{
if(get_dist(cinema,shop)+get_dist(shop,house)<l2+eps)
ans=min(l1,l2);
else
{
double l=0,r=min(l1,l2),mid;
while(l+eps<r)
{
mid=(l+r)/2.0;
if(jug(mid))
l=mid;
else
r=mid;
}
ans=r;
}
}
inline void print()
{
printf("%.10f",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}