(beginer)圆和圆相交 UVA 10969 - Sweet Dream
来源:互联网 发布:生产工艺流程图软件 编辑:程序博客网 时间:2024/06/06 01:13
Problem F
Sweet Dream
Are you ready to have a sweet dream? OK! Close your eyes (Hey! Do NOT! I was kidding! How can you read the problem statement with your eyes closed? Umm! Let me think . . . Yes! There is a good solution to this problem. Simply, hand this paper to your teammate and let him read it aloud for you)!
. . . You are standing in the middle of a room and you have a handful of discs of different sizes. They are heavy. You somehow feel uncomfortable. Calm down and don’t worry! I am going to help you feel comfortable again. Simply choose one of the discs in your hand randomly and drop it on the floor. Yes! You feel a little more comfortable. Choose and drop another! Then another one! . . . And continue this process until your hands are empty. Now, you are as light as a feather and you are ready to fly away . . .
But don’t be so quick! Before flying away, you should solve a problem. Open your eyes and take a look at the floor. You see the discs you’ve just dropped (To the teammate reading this problem aloud: Show the contents of figure 1 to your teammate who is going to open his eyes now).
Figure 1. Discs on the floor viewed from the above
You can see that some discs are partially (or totally) covered by other discs. Your job is to compute the total perimeter of parts of the discs that you can see from the above.
Umm! I think you feel a little bit uncomfortable again. Am I right?
The Input
The first line of input contains a single integer which is the number of test cases. Each test case starts with a single integer , the number of discs originally in your hand followed by lines, the th of which containing three floating-point numbers which are , radius of the th disc and the coordinates of the point on the floor on which the disc has fallen. Two floating-point numbers are assumed to be equal if their absolute difference is less than .
The Output
Output for each test case consists of a line containing a floating-point number which is the total perimeter of part of discs that can be seen from above rounded to 3 decimal digits after the fraction point. The number should have exactly 3 digits after the fraction point.
Sample Input
3
1
10 0 0
2
5 0 0
10 0 0
2
1 0 0
1 1 0
Sample Output
62.832
62.832
10.472
Amirkabir University of Technology - Local Contest - Round #2
题意:在平面上依次放置n个圆盘,后放的会覆盖之前放的,问最后能看到多长的弧长。
思路:我们对每个圆求出他与上层的圆的交点,然后得出了一段段的圆弧,然后我们判断每段圆弧是否被覆盖,未覆盖就算上,覆盖了就不算,是否覆盖可以取圆弧上任意一点看是否在上层的圆盘中。
代码:
#include<iostream>#include<cstdio>#include<string.h>#include<math.h>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define eps 1e-10const double PI = 4*atan(1.0);struct Point{Point (double xx=0,double yy=0) : x(xx) , y(yy) { }double x;double y;};typedef Point Vector;Vector operator+(Vector v1,Vector v2) { return Vector(v1.x+v2.x,v1.y+v2.y); }Vector operator-(Vector v1,Vector v2) { return Vector(v1.x-v2.x,v1.y-v2.y); }Vector operator*(Vector v, double p) { return Vector(v.x*p,v.y*p); }Vector operator/(Vector v,double p) { return Vector(v.x/p,v.y/p); }bool operator < (Point a,Point b) { return a.x < b.x || (a.x==b.x && a.y > b.y); }int dcmp(double x) {if (fabs(x) < eps) return 0;return x < 0 ? -1 : 1; }bool operator==(const Point & a,const Point & b) {return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;}inline double toRad(double x) { return x * PI/180; }inline double toDegreed(double rad) { return rad*180/PI; }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 Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; }double Area2(Point a,Point b,Point c) { return Cross(b-a,c-a); }Vector Rotate(Vector A,double rad) {return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y/L,A.x/L); }//点和直线Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){Vector u = P-Q;double t = Cross(w,u) / Cross(v,w);return P+v*t;}double DistanceToLine(Point P,Point A,Point B) {Vector v1 = B-A , v2 = P-A;return fabs(Cross(v1,v2))/Length(v1);}double DistanceToSegment(Point P,Point A,Point B){if (A==B) return Length(P-A);Vector v1 = B-A , v2 = P-A , v3 = P-B;if (dcmp(Dot(v1,v2)) < 0) return Length(v2);else if (dcmp(Dot(v1,v3)) > 0) return Length(v3);else return fabs(Cross(v1,v2))/Length(v1);}Point GetLineProjection(Point P,Point A,Point B) {Vector v = B-A;return A+v*(Dot(v,P-A)/Dot(v,v));}bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2) {double c1 = Cross(a2-a1,b1-a1) , c2 = Cross(a2-a1,b2-a1) , c3 = Cross(b2-b1,a1-b1) , c4 = Cross(b2-b1,a2-b1);return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4)<0;}bool OnSegment(Point p,Point a,Point b) {return dcmp(Cross(a-p,b-p))==0 && dcmp(Dot(a-p,b-p)) < 0;}//--------------------------------------------------------------------------------------------//直线和直线struct Line{Point P;//直线上任意一点Vector v;// 方向向量。它的左边就是对应的半平面double ang;//极角Line() { }Line(Point P,Vector v) : P(P) , v(v) { ang = atan2(v.y,v.x); }bool operator < (const Line& L) const { return ang < L. ang; } //排序用的比较运算符Point point(double x) { return v*(x-P.x)+P; }};//点p在有向直线L的左边(线上不算)bool OnLeft(Line L , Point p) { return Cross(L.v,p-L.P) > 0; }//二直线交点。假定交点唯一存在Point GetIntersection(Line a,Line b) {Vector u = a.P-b.P;double t = Cross(b.v,u) / Cross(a.v,b.v);return a.P+a.v*t;}//半平面交的过程int HalfplaneIntersection(Line* L,int n,Point* poly){sort(L,L+n); //按极角排序int first , last;//双端队列的第一个元素和最后一个元素的下表Point *p = new Point[n];//p[i]为q[i]和q[i+1]的交点Line *q = new Line[n];//双端队列q[first=last=0] = L[0];//双端队列初始化为只有一个半平面L[0]for (int i = 1 ; i < n ; ++i) {while (first < last && !OnLeft(L[i],p[last-1])) --last;while (first < last && !OnLeft(L[i],p[first])) ++first;q[++last] = L[i];if (fabs(Cross(q[last].v,q[last-1].v)) < eps) {--last;if (OnLeft(q[last],L[i].P)) q[last] = L[i];}if (first < last) p[last-1] = GetIntersection(q[last-1],q[last]);}while (first < last && !OnLeft(q[first],p[last-1])) --last;//删除无用平面(*)if (last - first <=1 ) return 0; //空集(**)p[last] = GetIntersection(q[last],q[first]);//计算首尾两个半平面的交点//从deque复制到输出中int m = 0;for (int i = first ; i <= last ; ++i) poly[m++] = p[i];return m ;}//--------------------------------------------//与圆相关struct Circle {Circle() { }Point c;double r;Circle(Point c, double r) : c(c) , r(r) { }Point point (double a) { return Point(c.x+cos(a)*r,c.y+sin(a)*r); }};int getLineCircleIntersection(Line L,Circle C,double &t1,double &t2,vector<Point>& sol){double a = L.v.x , b = L.P.x-C.c.x , c= L.v.y, d = L.P.y-C.c.y;double e = a*a+c*c , f = 2*(a*b+c*d) , g = b*b+d*d-C.r*C.r;double delta = f*f-4*e*g;//判别式if (dcmp(delta) < 0) return 0;//相离if (dcmp(delta)==0) { //相切t1 = t2 = -f/(2*e); sol.push_back(L.point(t1));return 1;}//相交t1 = (-f-sqrt(delta)) / (2*e); sol.push_back(L.point(t1));t2 = (-f+sqrt(delta))/(2*e); sol.push_back(L.point(t2));return 2;}double angle(Vector v) { return atan2(v.y,v.x); }int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol){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));//向量C1C2的极角//C1C2到C1P1的角Point p1 = C1.point(a-da) , p2 = C1.point(a+da);sol.push_back(p1);if (p1==p2) return 1;sol.push_back(p2);return 2;}//国电p到圆C的切线。v[i]是第i条切线的向量。返回切线条数int getTangents(Point p,Circle C,Vector* v){Vector u= C.c-p;double dist = Length(u);if (dist < C.r) return 0;else if (dcmp(dist-C.r)==0) {v[0] = Rotate(u,PI/2);return 1;} else {double ang = asin(C.r/dist);v[0] = Rotate(u,-ang);v[1] = Rotate(u,+ang);return 2;}}int getTangents(Circle A,Circle B,Point* a, Point* b){int cnt = 0;if (A.r < B.r) { swap(A,B); swap(a,b); }double d2 = Dot(A.c-B.c,A.c-B.c);double rdiff = A.r-B.r;double rsum = A.r+B.r;if (dcmp(d2-rdiff*rdiff) < 0) return 0;//内含double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);if (d2==0 && dcmp(A.r-B.r)==0) return -1;//无限多条切线if (dcmp(d2-rdiff*rdiff)==0) { //内切,1条切线a[cnt] = A.point(base);b[cnt] = B.point(base);++cnt;return 1;}//有外切共线double ang = acos((A.r-B.r)/sqrt(d2));a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang); ++cnt;a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang); ++cnt;if (dcmp(d2-rsum*rsum)==0) { //一条内公切线a[cnt] = A.point(base);b[cnt] = B.point(PI+base);++cnt;} else if (dcmp(d2-rsum*rsum)>0) { //两条公切线double ang = acos((A.r+B.r)/sqrt(d2));a[cnt] = A.point(base+ang); b[cnt] = B.point(PI+base+ang); ++cnt;a[cnt] = A.point(base-ang); b[cnt] = B.point(PI+base-ang); ++cnt;}return cnt;}bool InCircle(Circle A,Circle B){if (dcmp(A.r-B.r)>0) return false;double d2 = Dot(A.c-B.c,A.c-B.c);double rdiff = A.r-B.r;double rsum = A.r+B.r;if (dcmp(d2-rdiff*rdiff) <= 0) return true;//内含或内切或重合return false;}//----------------------------------------------------------------------------const int maxn = 110;int n;Circle circle[maxn];bool covered(Point p,int c) {for (int i = n-1 ; i > c ; --i) {if (dcmp(Length(p-circle[i].c)-circle[i].r)<=0)return true;}return false;}void input(){for (int i = 0 ; i < n ; ++i) {Circle & c = circle[i];scanf("%lf%lf%lf",&c.r,&c.c.x,&c.c.y);}}void solve(){double ans = 0;for (int i = 0 ; i < n ; ++i) {vector<Point> inter;for (int j = i+1 ; j < n ; ++j) getCircleCircleIntersection(circle[i],circle[j],inter);vector<double> rad;for (int j = 0 ; j < inter.size() ; ++j) rad.push_back(angle(inter[j]-circle[i].c)+PI);sort(rad.begin(),rad.end());if (rad.empty() || dcmp(rad[0])!=0) rad.insert(rad.begin(),0);if (rad.empty() || dcmp(rad[rad.size()-1]-2*PI)!=0) rad.insert(rad.end(),2*PI);double S = 0;for (int j = 0; j < rad.size()-1; ++j) {Point mid = circle[i].point((rad[j]-PI+rad[j+1]-PI)*0.5);if (covered(mid,i)) continue;S += rad[j+1]-rad[j];}ans += S*circle[i].r;}printf("%.3lf\n",ans);}int main(){int T; cin>>T;while (T--) {scanf("%d",&n);input();solve();}}
- (beginer)圆和圆相交 UVA 10969 - Sweet Dream
- UVA 10969 Sweet Dream(圆的相交)
- uva 10969 - Sweet Dream(几何)
- UVa 10969 Sweet Dream 继续圆盘问题
- uva 11177(凸多边形和圆的相交)
- sweet dream my baby!
- (beginer)DFS UVA 11396 Claw Decomposition
- (beginer)最短路 UVA 10603 Fill
- (beginer) 经纬度转换 UVA 10075 - Airlines
- (beginer) 凸包 UVA 1303 - Wall
- 判断圆和矩形是否相交(非面积相交)
- 判断圆和矩形是否相交(非面积相交)
- (beginer)DFS (dfs) UVA 10319 Manhattan
- (beginer)DFS (2-SAT) UVA 11294 Wedding
- (beginer)DFS (强连通)UVA 11504 Dominos
- (beginer) 最短路 UVA 10269 Adventure of Super Mario
- (beginer)最短路 UVA 11367 Full Tank?
- (beginer) 最小生成树 UVA 1395 Slim Span
- 10557 - XYZZY(dfs + bfs)
- cf 227 除夕夜
- tmx加载出错m_uMaxGID >= m_pTileSet->m_uFirstGid
- 《学习OpenCV》练习5-4
- py2exe使用方法
- (beginer)圆和圆相交 UVA 10969 - Sweet Dream
- 一步一步打造Vim+Eclipse+Eclim开发环境 -- 第一篇 Eclim安装
- bat文件浅析(一)
- 2014年2月15日 19:04:39
- 面向对象基础知识(5)- 封装 继承 多态
- Android照相功能驱动层中HAL的实现(基于OK6410开发板+OV9650摄像头)
- hdu 1217 && poj2240 Arbitrage 最短路
- Open .pdf on ubuntu
- NVelocity用法