码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces #8D Two Friends 二分答案+计算几何

时间:2015-05-14 14:23:57      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:codeforces   二分答案   计算几何   

题目大意:给定平面上的三个点A,B,CAlan需要从A走到C再走到BBob需要从A直接走到B,要求Alan走过的长度不能超过最短路长度+t1Bob走过的长度不能超过最短路长度+t2,求两人在一起最多走多久(分开后再汇合不算一起走)

Alan最多走L1Bob最多走L2
首先如果Bob能陪伴Alan全程(即L2Distance(A,C)+Distance(C,B)),那么答案显然为min(L1,L2)
否则两人分离时Bob一定还没有经过C
容易发现答案是单调的,我们不妨二分答案
不妨设分离点为P,当前二分到mid,那么:
Distance(P,A)mid
Distance(P,B)L2?mid
Distance(P,C)L1?Distance(B,C)?mid
容易发现每个不等式中P的范围都是一个圆
因此我们只需要判断三个圆是否有公共部分即可
具体怎么做自己玩去吧 注意精度

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define EPS 1e-15
#define PI 3.1415926535897932
using namespace std;
typedef long double ld;
struct Point{
    ld x,y;
    Point() {}
    Point(ld _,ld __):
        x(_),y(__) {}
    friend istream& operator >> (istream &_,Point &p)
    {
        return _>>p.x>>p.y;
    }
    friend Point operator + (const Point &p1,const Point &p2)
    {
        return Point(p1.x+p2.x,p1.y+p2.y);
    }
    friend Point operator - (const Point &p1,const Point &p2)
    {
        return Point(p1.x-p2.x,p1.y-p2.y);
    }
    friend ld Distance(const Point &p1,const Point &p2)
    {
        return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) );
    }
    friend ld Arctan2(const Point &p)
    {
        return atan2(p.y,p.x);
    }
}A,B,C;
struct Interval{
    ld l,r;
    Interval() {}
    Interval(ld _,ld __):
        l(_),r(__) {}
    bool In_Interval(ld x) const
    {
        return x>=l && x<=r ;
    }
    friend bool Intersect(const Interval &i1,const Interval &i2)
    {
        return i1.In_Interval(i2.l) || i1.In_Interval(i2.r) || i2.In_Interval(i1.l) ;
    }
};
struct Circle{
    Point o;
    ld r;
    Circle() {}
    Circle(const Point &_,const ld &__):
        o(_),r(__) {}
    friend bool Seperated(const Circle &c1,const Circle &c2)
    {
        return Distance(c1.o,c2.o) > c1.r + c2.r + EPS ;
    }
    friend bool Include(const Circle &c1,const Circle &c2)
    {
        return Distance(c1.o,c2.o) < fabs(c1.r-c2.r) ;
    }
    friend Interval Get_Intersection(const Circle &c1,const Circle &c2)
    {
        ld alpha=Arctan2(c2.o-c1.o);
        ld a=c1.r;
        ld b=Distance(c1.o,c2.o)-EPS;
        ld c=c2.r;
        ld delta=acos( (a*a+b*b-c*c)/(2*a*b) );
        return Interval(alpha-delta,alpha+delta);
    }
};

ld t1,t2;
bool Check(const Circle &c1,const Circle &c2,const Circle &c3)
{
    Interval i1=Get_Intersection(c1,c2);
    Interval i2=Get_Intersection(c1,c3);
    if( Intersect(i1,i2) )
        return true;
    i1.l+=2*PI;i1.r+=2*PI;
    if( Intersect(i1,i2) )
        return true;
    i1.l-=4*PI;i1.r-=4*PI;
    if( Intersect(i1,i2) )
        return true;
    return false;
}
bool Judge(ld mid)
{
    Circle c1(A,mid);
    Circle c2(B,t1-mid);
    Circle c3(C,t2-Distance(B,C)-mid);
    if( Seperated(c1,c2) || Seperated(c1,c3) || Seperated(c2,c3) )
        return false;
    if( Include(c1,c2) || Include(c1,c3) || Include(c2,c3) )
        return true;
    return Check(c1,c2,c3) || Check(c2,c1,c3) || Check(c3,c1,c2) ;
}
ld Bisection()
{
    ld l=0,r=min(t1,t2-Distance(B,C));
    while(r-l>EPS)
    {
        ld mid=(l+r)/2;
        if(Judge(mid))
            l=mid;
        else
            r=mid;
    }
    return (l+r)/2;
}
int main()
{
    cin>>t2>>t1>>A>>B>>C;
    t1+=Distance(A,B);
    t2+=Distance(A,C);
    t2+=Distance(B,C);
    if( t1>=Distance(A,C)+Distance(B,C) )
        return cout<<fixed<<setprecision(10)<<min(t1,t2)<<endl,0;
    cout<<fixed<<setprecision(10)<<Bisection()<<endl;
    return 0;
}

codeforces #8D Two Friends 二分答案+计算几何

标签:codeforces   二分答案   计算几何   

原文地址:http://blog.csdn.net/popoqqq/article/details/45719007

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!