多边形和圆的相交面积(模板)hdu2892、hdu4404
area
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 686 Accepted Submission(s): 265
Problem Description
小白最近被空军特招为飞行员,参与一项实战演习。演习的内容是轰炸某个岛屿。。。
作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某个位置,可是长官更关心的是,小白投掷的炸弹到底摧毁了岛上多大的区域?
岛是一个不规则的多边形,而炸弹的爆炸半径为R。
小白只知道自己在(x,y,h)的空间坐标处以(x1,y1,0)的速度水平飞行时投下的炸弹,请你计算出小白所摧毁的岛屿的面积有多大. 重力加速度G = 10.
作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某个位置,可是长官更关心的是,小白投掷的炸弹到底摧毁了岛上多大的区域?
岛是一个不规则的多边形,而炸弹的爆炸半径为R。
小白只知道自己在(x,y,h)的空间坐标处以(x1,y1,0)的速度水平飞行时投下的炸弹,请你计算出小白所摧毁的岛屿的面积有多大. 重力加速度G = 10.
Input
首先输入三个数代表小白投弹的坐标(x,y,h);
然后输入两个数代表飞机当前的速度(x1, y1);
接着输入炸弹的爆炸半径R;
再输入一个数n,代表岛屿由n个点组成;
最后输入n行,每行输入一个(x',y')坐标,代表岛屿的顶点(按顺势针或者逆时针给出)。(3<= n < 100000)
然后输入两个数代表飞机当前的速度(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"cstdio" #include"cstring" #include"cstdlib" #include"cmath" #include"string" #include"map" #include"cstring" #include"algorithm" #include"iostream" #include"set" #include"queue" #include"stack" #define inf 1000000000000 #define M 100009 #define LL long long #define eps 1e-12 #define mod 1000000007 #define PI acos(-1.0) using namespace std; struct node { double x,y; node(){} node(double xx,double yy) { x=xx; y=yy; } node operator -(node s) { return node(x-s.x,y-s.y); } node operator +(node s) { return node(x+s.x,y+s.y); } double operator *(node s) { return x*s.x+y*s.y; } double operator ^(node s) { return x*s.y-y*s.x; } }p[M]; double max(double a,double b) { return a>b?a:b; } double min(double a,double b) { return a<b?a:b; } double len(node a) { return sqrt(a*a); } double dis(node a,node b)//两点之间的距离 { return len(b-a); } double cross(node a,node b,node c)//叉乘 { return (b-a)^(c-a); } double dot(node a,node b,node c)//点成 { return (b-a)*(c-a); } int judge(node a,node b,node c)//判断c是否在ab线段上(前提是c在直线ab上) { if(c.x>=min(a.x,b.x) &&c.x<=max(a.x,b.x) &&c.y>=min(a.y,b.y) &&c.y<=max(a.y,b.y)) return 1; return 0; } double area(node b,node c,double r) { node a(0.0,0.0); if(dis(b,c)<eps) return 0.0; double h=fabs(cross(a,b,c))/dis(b,c); if(dis(a,b)>r-eps&&dis(a,c)>r-eps)//两个端点都在圆的外面则分为两种情况 { double angle=acos(dot(a,b,c)/dis(a,b)/dis(a,c)); if(h>r-eps) { return 0.5*r*r*angle; } else if(dot(b,a,c)>0&&dot(c,a,b)>0) { double angle1=2*acos(h/r); return 0.5*r*r*fabs(angle-angle1)+0.5*r*r*sin(angle1); } else { return 0.5*r*r*angle; } } else if(dis(a,b)<r+eps&&dis(a,c)<r+eps)//两个端点都在圆内的情况 { return 0.5*fabs(cross(a,b,c)); } else//一个端点在圆上一个端点在圆内的情况 { if(dis(a,b)>dis(a,c))//默认b在圆内 { swap(b,c); } if(fabs(dis(a,b))<eps)//ab距离为0直接返回0 { return 0.0; } if(dot(b,a,c)<eps) { double angle1=acos(h/dis(a,b)); double angle2=acos(h/r)-angle1; double angle3=acos(h/dis(a,c))-acos(h/r); return 0.5*dis(a,b)*r*sin(angle2)+0.5*r*r*angle3; } else { double angle1=acos(h/dis(a,b)); double angle2=acos(h/r); double angle3=acos(h/dis(a,c))-angle2; return 0.5*r*dis(a,b)*sin(angle1+angle2)+0.5*r*r*angle3; } } } int main() { double x,y,h,x1,y1,R; while(scanf("%lf%lf%lf",&x,&y,&h)!=-1) { scanf("%lf%lf%lf",&x1,&y1,&R); int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } p[n]=p[0]; double V=sqrt(2*10*h); double t0=V/10; double x0=x+x1*t0; double y0=y+y1*t0; node O(x0,y0); for(int i=0;i<=n;i++) p[i]=p[i]-O; O=node(0,0); double sum=0; for(int i=0;i<n;i++) { int j=i+1; double s=area(p[i],p[j],R); if(cross(O,p[i],p[j])>0) sum+=s; else sum-=s; } printf("%.2lf\n",fabs(sum)); } return 0; }