hdu 2892 area
area
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 717 Accepted Submission(s): 280
Problem Description
小白最近被空军特招为飞行员,参与一项实战演习。演习的内容是轰炸某个岛屿。。。 作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某个位置,可是长官更关心的是,小白投掷的炸弹到底摧毁了岛上多大的区域? 岛是一个不规则的多边形,而炸弹的爆炸半径为R。 小白只知道自己在(x,y,h)的空间坐标处以(x1,y1,0)的速度水平飞行时投下的炸弹,请你计算出小白所摧毁的岛屿的面积有多大. 重力加速度G = 10.
Input
首先输入三个数代表小白投弹的坐标(x,y,h); 然后输入两个数代表飞机当前的速度(x1, y1); 接着输入炸弹的爆炸半径R; 再输入一个数n,代表岛屿由n个点组成; 最后输入n行,每行输入一个(x',y')坐标,代表岛屿的顶点(按顺势针或者逆时针给出)。(3<= n < 100000)
Output
输出一个两位小数,表示实际轰炸到的岛屿的面积。
Sample Input
0 0 2000
100 0
100
4
1900 100
2000 100
2000 -100
1900 -100
Sample Output
15707.96
多边形与圆交
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<algorithm> using namespace std; typedef long long LL; const double PI = acos(-1.0); const double EPS = 1e-8; inline int sgn(double x) { return (x > EPS) - (x < -EPS); } struct Point { double x, y; Point() {} Point(double x, double y): x(x), y(y) {} void read() { scanf("%lf%lf", &x, &y); } double angle() { return atan2(y, x); } Point operator + (const Point &rhs) const { return Point(x + rhs.x, y + rhs.y); } Point operator - (const Point &rhs) const { return Point(x - rhs.x, y - rhs.y); } Point operator * (double t) const { return Point(x * t, y * t); } Point operator / (double t) const { return Point(x / t, y / t); } double operator *(const Point &b)const { return x*b.x + y*b.y; } double length() const { return sqrt(x * x + y * y); } Point unit() const { //单位向量 double l = length(); return Point(x / l, y / l); } }; double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; } double sqr(double x) { return x * x; } double dist(const Point &p1, const Point &p2) { return (p1 - p2).length(); } double sdist(Point a,Point b){ return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } //向量 op 逆时针旋转 angle Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) { Point t = p - o; double x = t.x * cos(angle) - t.y * sin(angle); double y = t.y * cos(angle) + t.x * sin(angle); return Point(x, y) + o; } Point line_inter(Point A,Point B,Point C,Point D){ //直线相交交点 Point ans; double a1=A.y-B.y; double b1=B.x-A.x; double c1=A.x*B.y-B.x*A.y; double a2=C.y-D.y; double b2=D.x-C.x; double c2=C.x*D.y-D.x*C.y; ans.x=(b1*c2-b2*c1)/(a1*b2-a2*b1); ans.y=(a2*c1-a1*c2)/(a1*b2-a2*b1); return ans; } Point p_to_seg(Point p,Point a,Point b){ //点到线段的最近点 Point tmp=p; tmp.x+=a.y-b.y; tmp.y+=b.x-a.x; if(cross(a-p,tmp-p)*cross(b-p,tmp-p)>0) return dist(p,a)<dist(p,b)?a:b; return line_inter(p,tmp,a,b); } void line_circle(Point c,double r,Point a,Point b,Point &p1,Point &p2){ Point tmp=c; double t; tmp.x+=(a.y-b.y);//求垂直于ab的直线 tmp.y+=(b.x-a.x); tmp=line_inter(tmp,c,a,b); t=sqrt(sqr(r)-sqr( dist(c,tmp)))/dist(a,b); //比例 p1.x=tmp.x+(b.x-a.x)*t; p1.y=tmp.y+(b.y-a.y)*t; p2.x=tmp.x-(b.x-a.x)*t; p2.y=tmp.y-(b.y-a.y)*t; } struct Region { double st, ed; Region() {} Region(double st, double ed): st(st), ed(ed) {} bool operator < (const Region &rhs) const { if(sgn(st - rhs.st)) return st < rhs.st; return ed < rhs.ed; } }; struct Circle { Point c; double r; vector<Region> reg; Circle() {} Circle(Point c, double r): c(c), r(r) {} void read() { c.read(); scanf("%lf", &r); } void add(const Region &r) { reg.push_back(r); } bool contain(const Circle &cir) const { return sgn(dist(cir.c, c) + cir.r - r) <= 0; } bool intersect(const Circle &cir) const { return sgn(dist(cir.c, c) - cir.r - r) < 0; } }; void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) { //两圆相交 交点 double l = dist(cir1.c, cir2.c); //两圆心的距离 double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / (2 * l); //cir1圆心到交点直线的距离 double d2 = sqrt(sqr(cir1.r) - sqr(d)); //交点到 两圆心所在直线的距离 Point mid = cir1.c + (cir2.c - cir1.c).unit() * d; Point v = rotate(cir2.c - cir1.c, PI / 2).unit() * d2; p1 = mid + v, p2 = mid - v; } Point calc(const Circle &cir, double angle) { Point p = Point(cir.c.x + cir.r, cir.c.y); return rotate(p, angle, cir.c); } const int MAXN = 1010; Circle cir[MAXN],cir2[MAXN]; bool del[MAXN]; int n; double get_area(Circle* cir,int n) { //多个圆的相交面积 double ans = 0; memset(del,0,sizeof(del)); for(int i = 0; i < n; ++i) { for(int j = 0; j < n; ++j) if(!del[j]) { //删除被包含的圆 if(i == j) continue; if(cir[j].contain(cir[i])) { del[i] = true; break; } } } for(int i = 0; i < n; ++i) if(!del[i]) { Circle &mc = cir[i]; Point p1, p2; bool flag = false; for(int j = 0; j < n; ++j) if(!del[j]) { if(i == j) continue; if(!mc.intersect(cir[j])) continue; flag = true; intersection(mc, cir[j], p1, p2); //求出两圆的交点 double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle(); if(sgn(rs) < 0) rs += 2 * PI; if(sgn(rt) < 0) rt += 2 * PI; if(sgn(rs - rt) > 0) mc.add(Region(rs, PI * 2)), mc.add(Region(0, rt)); //添加相交区域 else mc.add(Region(rs, rt)); } if(!flag) { ans += PI * sqr(mc.r); continue; } sort(mc.reg.begin(), mc.reg.end()); //对相交区域进行排序 int cnt = 1; for(int j = 1; j < int(mc.reg.size()); ++j) { if(sgn(mc.reg[cnt - 1].ed - mc.reg[j].st) >= 0) { //如果有区域可以合并,则合并 mc.reg[cnt - 1].ed = max(mc.reg[cnt - 1].ed, mc.reg[j].ed); } else mc.reg[cnt++] = mc.reg[j]; } mc.add(Region()); mc.reg[cnt] = mc.reg[0]; for(int j = 0; j < cnt; ++j) { p1 = calc(mc, mc.reg[j].ed); p2 = calc(mc, mc.reg[j + 1].st); ans += cross(p1, p2) / 2; // double angle = mc.reg[j + 1].st - mc.reg[j].ed; if(sgn(angle) < 0) angle += 2 * PI; ans += 0.5 * sqr(mc.r) * (angle - sin(angle)); //弧所对应的的面积 } } return ans; } double two_cir(Circle t1,Circle t2){ //两个圆的相交面积 if(t1.contain(t2)||t2.contain(t1)) return PI * sqr(min(t2.r,t1.r)); if(!t1.intersect(t2)) return 0; double ans=0,len=dist(t1.c,t2.c); double x=(sqr(t1.r)+sqr(len)-sqr(t2.r))/(2*len); double angle1=acos(x/t1.r),angle2=acos((len-x)/t2.r); ans=sqr(t1.r)*angle1+sqr(t2.r)*angle2-len*t1.r*sin(angle1); // 两个扇形 减去一个四边形面积 return ans; } double triangle_circle(Point a,Point b,Point o,double r){ double sign=1.0; double ans=0; Point p1,p2; a=a-o;b=b-o; o=Point(0,0); if(sgn(cross(a,b))==0) return 0.0; if(sdist(a,o)>sdist(b,o)){ swap(a,b); sign=-1.0; } if(sdist(a,o)<r*r+EPS){ //a 在内, b 在外 if(sdist(b,o)<r*r+EPS) return cross(a,b)/2.0*sign; line_circle(o,r,a,b,p1,p2); if(dist(p1,b)>dist(p2,b)) swap(p1,p2); double ans1=fabs(cross(a,p1)); double ans2=acos(p1*b/p1.length()/b.length())*r*r; ans=(ans1+ans2)/2.0; if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans; return ans; } Point tmp=p_to_seg(o,a,b); if(sdist(o,tmp)>r*r-EPS){ //a,b所在直线与圆没有交点 double angle=a*b/a.length()/b.length(); if(angle>1.0) angle=1; if(angle<-1.0) angle=-1.0; ans=acos(a*b/a.length()/b.length())*r*r/2.0; if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans; return ans; } line_circle(o,r,a,b,p1,p2); double cm=r/(dist(a,o)-r); Point m=Point((o.x+cm*a.x)/(1+cm),(o.y+cm*a.y)/(1+cm) ); double cn=r/(dist(o,b)-r); Point n=Point( (o.x+cn*b.x)/(1+cn) , (o.y+cn*b.y)/(1+cn) ); double angle= m*n/m.length()/n.length(); if(angle>1.0) angle=1; if(angle<-1.0) angle=-1.0; double ans1 = acos(m*n/m.length()/n.length())*r*r; angle=p1*p2/p1.length()/p2.length() ; if(angle>1.0) angle=1; if(angle<-1.0) angle=-1.0; double ans2 = acos(p1*p2/p1.length()/p2.length() )*r*r-fabs(cross(p1,p2)); ans=(ans1-ans2)/2.0; if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans; return ans; } int main() { #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif // ONLINE_JUDGE Point a,b,c; double x1,y1,h,x2,y2,r,t; while(scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&h,&x2,&y2,&r)!=EOF){ int n;cin>>n; Point pt[101010]; for(int i=0;i<n;i++) pt[i].read(); t=sqrt(2.0*h/10); c.x=x1;c.y=y1; c.x+=t*x2; c.y+=t*y2; pt[n]=pt[0]; double ans=0; for(int i=0;i<n;i++) ans+=triangle_circle(pt[i],pt[i+1],c,r); printf("%.2f\n",fabs(ans)+EPS); } }