codeforces 8D 二分后判断3个圆是否有交集

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/86588884

这题一开始看错题了,原来最多的走的距离是它本身走的最短距离+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

#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 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 sita,cosval=(ra*ra+len*len-rb*rb)/(2*ra*len);
	if(cosval<-1.0)
		cosval+=eps;
	if(cosval>1.0)
		cosval-=eps; 
	sita=acos(cosval);
	point vec=b-a;
	vec.transxy(sita);
	double t=(ra/sqrt(vec*vec));
	intersec1=a+point(vec.x*t,vec.y*t);
	vec=b-a;
	vec.transxy(2*pi-sita);
	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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/86588884