同swustoj 8
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1015 | Accepted: 341 |
Description
Input
Output
Sample Input
3 500 500 499 0 0 999 1000 1000 200
Sample Output
Bill enters at (0.00, 1000.00) and leaves at (1000.00, 800.00).
并查集+计算几何
#include<iostream> #include<algorithm> #include<cmath> #include<vector> #include<cstdio> using namespace std; #define PI acos(-1.0) #define EPS 1e-8 #define N 1010 int dcmp(double x) { if(fabs(x)<EPS) return 0; return x<0?-1:1; } struct Point { double x,y; Point (){} Point (double x,double y):x(x),y(y){} Point operator - (Point p){ return Point(x-p.x,y-p.y); } bool operator == (Point p){ return dcmp(fabs(x-p.x))==0 && dcmp(fabs(y-p.y))==0; } double operator * (Point p){ return x*p.x+y*p.y; } double operator ^ (Point p){ return x*p.y-y*p.x; } double length(){ return sqrt(x*x+y*y); } double angle(){ return atan2(y,x); } bool operator <(const Point &p)const{ return y<p.y; } }; struct Line { Point s,e; Line (){} Line (Point s,Point e):s(s),e(e){} Point GetPoint(double t){ return Point(s.x+(e.x-s.x)*t,s.y+(e.y-s.y)*t); } }; struct Circle { Point c; double r; Circle(){} Circle(Point c,double r):c(c),r(r){} Point GetPoint(double a){ return Point(c.x+cos(a)*r,c.y+sin(a)*r); } /* 0表示相离,1表示相切,2表示相交 */ pair<int,vector<Point> > CircleInterLine(Line l){ vector<Point> res; double A=l.e.x-l.s.x,B=l.s.x-c.x,C=l.e.y-l.s.y,D=l.s.y-c.y; double E=A*A+C*C,F=2*(A*B+C*D),G=B*B+D*D-r*r; double delta=F*F-4*E*G; if(dcmp(delta)<0) return make_pair(0,res); if(dcmp(delta)==0){ res.push_back(l.GetPoint(-F/(2*E))); return make_pair(1,res); } res.push_back(l.GetPoint((-F-sqrt(delta))/(2*E))); res.push_back(l.GetPoint((-F+sqrt(delta))/(2*E))); return make_pair(2,res); } /* -1表示重合,0表示相离,1表示相切,2表示相交 */ int operator & (Circle C){ double d=(c-C.c).length(); if(dcmp(d)==0){ if(dcmp(r-C.r)==0) return -1; return 0; } if(dcmp(r+C.r-d)<0) return 0; if(dcmp(fabs(r-C.r)-d)>0) return 0; double a=(C.c-c).angle(); double da=acos((r*r+d*d-C.r*C.r)/(2*r*d)); Point p1=GetPoint(a-da),p2=GetPoint(a+da); if(p1==p2) return 1; return 2; } }; int n; int f[N]; Line up,down; Line lft,rgt; Circle c[N]; void init() { for(int i=0;i<=n+1;i++) f[i]=i; up=Line(Point(0,1000),Point(1000,1000)); down=Line(Point(0,0),Point(1000,0)); lft=Line(Point(0,0),Point(0,1000)); rgt=Line(Point(1000,0),Point(1000,1000)); } int Find(int x) { if(x!=f[x]) f[x]=Find(f[x]); return f[x]; } void UN(int x,int y) { x=Find(x); y=Find(y); if(x!=y) f[x]=y; } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&c[i].c.x,&c[i].c.y,&c[i].r); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if((c[i]&c[j])!=0){ UN(i,j); } } } //上边界 for(int i=1;i<=n;i++){ pair<int,vector<Point> > res=c[i].CircleInterLine(up); if(res.first!=0) UN(0,i); } //下边界 for(int i=1;i<=n;i++){ pair<int,vector<Point> > res=c[i].CircleInterLine(down); if(res.first!=0) UN(i,n+1); } if(Find(0)==Find(n+1)){ //出不去 printf("Bill will be bitten.\n"); continue; } //左右边界 vector<Point> p1,p2; p1.push_back(Point(0,1000)); p2.push_back(Point(1000,1000)); for(int i=1;i<=n;i++){ pair<int,vector<Point> > res1=c[i].CircleInterLine(lft); pair<int,vector<Point> > res2=c[i].CircleInterLine(rgt); if(res1.first!=0){ while(!res1.second.empty()){ if(res1.second.back().y>=0 && res1.second.back().y<=1000 && Find(i)==Find(0)) p1.push_back(res1.second.back()); res1.second.pop_back(); } } if(res2.first!=0){ while(!res2.second.empty()){ if(res2.second.back().y>=0 && res2.second.back().y<=1000 && Find(i)==Find(0)) p2.push_back(res2.second.back()); res2.second.pop_back(); } } } int i,j; sort(p1.begin(),p1.end()); sort(p2.begin(),p2.end()); printf("Bill enters at (0.00, %.2f) and leaves at (1000.00, %.2f).\n",p1[0].y,p2[0].y); } return 0; }