LA 2572 - Viva Confetti
2014-04-06 08:47
330 查看
这道题是训练指南上面的例题,判断小圆弧的时候,求出一个圆跟其它所有圆的交点,然后判断两个相邻交点之间的中点。如果这个中点没有在这个圆上面的所有圆里面,那么这个交点就没有被挡住,也就是说这个圆可见。然后这个交点下面的第一个圆也是可见的。
做的时候看了一下别人的博客,然后自作聪明的把判断两个圆相交的函数改了。本来的函数里面是求圆C1跟C2的交点,求完焦点以后只把容器C1里面加入交点的极角,这样循环的时候就需要
for(int i=0;i<n;++i){
for(int t=0;t<n;++t){
CircleCircleIntersection(i,t);
}
}
我想把它改成
for(int i=0;i<n;++i){
for(int t=i+1;t<n;++t){
CircleCircleIntersection(i,t);
}
}
这样在圆相交的函数里面一次就需要修改C1跟C2的容器。这样就一直错。开始没看出来什么函数错了,一直在找,后来发现是求C2的极角的时候出问题了,修改过来就对了。但是还是不能一次把两个圆的交点一起求。
找了好长时间错误,终于找到错那了。。我加的那些计算每错,错的地方是精确度。题目要求精确度是加减五乘十的负十三次方,我把eps设置成了十的负十三次放。把精确度改过来以后,怎么写怎么对。。
代码如下:
做的时候看了一下别人的博客,然后自作聪明的把判断两个圆相交的函数改了。本来的函数里面是求圆C1跟C2的交点,求完焦点以后只把容器C1里面加入交点的极角,这样循环的时候就需要
for(int i=0;i<n;++i){
for(int t=0;t<n;++t){
CircleCircleIntersection(i,t);
}
}
我想把它改成
for(int i=0;i<n;++i){
for(int t=i+1;t<n;++t){
CircleCircleIntersection(i,t);
}
}
这样在圆相交的函数里面一次就需要修改C1跟C2的容器。这样就一直错。开始没看出来什么函数错了,一直在找,后来发现是求C2的极角的时候出问题了,修改过来就对了。但是还是不能一次把两个圆的交点一起求。
找了好长时间错误,终于找到错那了。。我加的那些计算每错,错的地方是精确度。题目要求精确度是加减五乘十的负十三次方,我把eps设置成了十的负十三次放。把精确度改过来以后,怎么写怎么对。。
代码如下:
#include<iostream> #include<cmath> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn=105; const double pi=cos(-1); struct Point{ double x,y; Point(double x,double y):x(x),y(y){} }; typedef Point Vector; Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);} Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);} Vector operator * (Vector a,double p){return Vector(a.x*p,a.y*p);} Vector operator / (Vector a,double p){return Vector(a.x/p,a.y/p);} bool operator < (const Point& a,const Point& b){ return a.x<b.x||(a.x==b.x&&a.y<b.y); } const double eps=1e-14; int dcmp(double x){ if(fabs(x)<eps)return 0; return x<0?-1:1; } bool operator == (const Point& a ,Point& b){ return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; } struct Circle{ Point c; double r; Circle(Point c=Point(0,0),double r=0):c(c),r(r){} Point point(double a){ return Point(c.x+cos(a)*r, c.y+sin(a)*r); } }; double Dot(Vector a,Vector b){ return a.x*b.x+a.y*b.y; } double Length(Vector A){ return sqrt(Dot(A,A)); } double Angle(Vector a,Vector b){//ÏòÁ¿¼Ð½Ç return acos(Dot(a,b)/Length(a)/Length(b)); } double angle(Vector a){//ÏòÁ¿µÄ¼«½Ç return atan2(a.y,a.x); } int n; vector<double> pointAng[maxn]; Circle C[maxn]; int vis[maxn]; bool PointInCircle(Point p,Circle C){ if(dcmp(Length(p-C.c)-C.r)<0)return 1; return 0; } bool CircleInCircle(int c1,int c2){ Circle C1=C[c1]; Circle C2=C[c2]; double d=Length(C1.c-C2.c); if(dcmp(d)==0){ if(dcmp(C1.r-C2.r)<=0)return 1; return 0; } if(dcmp(C2.r-C1.r-d)>0)return 1; return 0; } int CircleCircleIntersection(int c1,int c2){ // cout<<"c1="<<c1<<' '<<"c2="<<c2<<endl; Circle C1=C[c1]; Circle C2=C[c2]; double d=Length(C1.c-C2.c); if(dcmp(d)==0){ if(dcmp(C1.r-C2.r)==0)return -1; return 0; } if(dcmp(C1.r+C2.r-d)<0)return 0; if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0; double a=angle(C2.c-C1.c); double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d)); // cout<<"///"<<C1.r<<' '<<C2.r<<' '<<d<<' '<<(C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d)<<endl; Point p1 =C1.point(a-da),p2=C1.point(a+da); // cout<<c1<<' '<<c2<<' '<<"C1 "<<C1.c.x<<' '<<C1.c.y<<' '<<C1.r<<' '<<C2.c.x<<' '<<C2.c.y<<' '<<C2.r<<" zz "<<p1.x<<' '<<p1.y<<' '<<p2.x<<' '<<p2.y<<"a="<<a<<' '<<"da="<<da<<endl; if(p1==p2)return 1; pointAng[c1].push_back(a-da); pointAng[c1].push_back(a+da); // double a2=pi+a; // if(a2<-pi)a2+=(2*pi); // if(a2>pi)a2-=(2*pi); // da=Angle(p1-C2.c,C1.c-C2.c); double pa1=angle(p1-C2.c); double pa2=angle(p2-C2.c); pointAng[c2].push_back(pa1); pointAng[c2].push_back(pa2); // a=angle(C1.c-C2.c); // da=acos((C2.r*C2.r+d*d-C1.r*C1.r)/(2*C2.r*d)); // pointAng[c2].push_back(a-da); // pointAng[c2].push_back(a+da); return 2; } void solve(){ memset(vis,0,sizeof(vis)); for(int i=0;i<n;++i){ for(int t=i+1;t<n;++t){ // cout<<"i="<<i<<' '<<"t="<<t<<endl; CircleCircleIntersection(t,i); } } for(int i=0;i<n;++i){ if(!pointAng[i].size())continue; sort(pointAng[i].begin(),pointAng[i].end()); vector<double>::iterator iter=unique(pointAng[i].begin(),pointAng[i].end()); pointAng[i].resize(iter-pointAng[i].begin()); } for(int i=0;i<n;++i){ int ez=pointAng[i].size(); if(!ez){ bool can=1; for(int t=i+1;t<n;++t){ if(CircleInCircle(i,t)){can=0;break;} } if(can)vis[i]=1; } else{ pointAng[i].push_back(pointAng[i][0]); for(int j=0;j<pointAng[i].size();++j){ Point midpoint=C[i].point((pointAng[i][j]+pointAng[i][j+1])/2); bool can=1; for(int k=i+1;k<n;++k){ if(PointInCircle(midpoint,C[k])){can=0;break;} } // cout<<i<<' '<<j<<' '<<pointAng[i].size()<<' '<<midpoint.x<<' '<<midpoint.y<<' '<<(midpoint.x-C[i].c.x)*(midpoint.x-C[i].c.x)+(midpoint.y-C[i].c.y)*(midpoint.y-C[i].c.y)<<' '<<can<<endl; if(can){ vis[i]=1; for(int k=i-1;k>=0;--k){ if(PointInCircle(midpoint,C[k])){ // cout<<"tttttttttt"<<endl; vis[k]=1;break;} } } } } } int ans=0; for(int i=0;i<n;++i){ if(vis[i])ans++; } cout<<ans<<endl; } int main(){ // freopen("data.txt","r",stdin); ios::sync_with_stdio(false); while(cin>>n){ if(n==0)break; for(int i=0;i<n;++i){ cin>>C[i].c.x>>C[i].c.y>>C[i].r; } solve(); } return 0; }
相关文章推荐
- LA 2572 Viva Confetti 离散化 *
- 【LA 2572】Viva Confetti, Kanazawa 2002 (计算几何,圆)
- LA 2572 Viva Confetti (Geometry.Circle)
- LA - 2572 - Viva Confetti
- LA 2572 Viva Confetti Kanazawa - 2002/2003 平面上的圆盘
- Viva Confetti UVALive - 2572
- UVALive - 2572 Viva Confetti 极角排序
- UVaLive2572 poj1418 UVa1308 Viva Confetti
- uva 1308 - Viva Confetti
- LA 2572 (求可见圆盘的数量) Kanazawa
- uva 1308 - Viva Confetti(几何)
- poj 1418 Viva Confetti
- Viva Confetti(几何+圆盘覆盖问题)
- POJ 1418 Viva Confetti 已翻译
- 圆弧并 uva 10969 && LA 2572
- zoj 1696 Viva Confetti
- POJ 1418 Viva Confetti
- 最近看到BillBord排行第一的歌曲Viva La Vida,很喜欢,推荐一下。^_^
- poj 1418 || zoj 1696 Viva Confetti
- 《viva la vida》 歌词