您的位置:首页 > 其它

hdu 2892 多边形与园面积相交

2014-05-07 12:54 471 查看

area

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 623    Accepted Submission(s): 233


[align=left]Problem Description[/align]
小白最近被空军特招为飞行员,参与一项实战演习。演习的内容是轰炸某个岛屿。。。

作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某个位置,可是长官更关心的是,小白投掷的炸弹到底摧毁了岛上多大的区域?

岛是一个不规则的多边形,而炸弹的爆炸半径为R。

小白只知道自己在(x,y,h)的空间坐标处以(x1,y1,0)的速度水平飞行时投下的炸弹,请你计算出小白所摧毁的岛屿的面积有多大. 重力加速度G = 10.

 

[align=left]Input[/align]
首先输入三个数代表小白投弹的坐标(x,y,h);

然后输入两个数代表飞机当前的速度(x1, y1);

接着输入炸弹的爆炸半径R;

再输入一个数n,代表岛屿由n个点组成;

最后输入n行,每行输入一个(x',y')坐标,代表岛屿的顶点(按顺势针或者逆时针给出)。(3<= n < 100000)

 

[align=left]Output[/align]
输出一个两位小数,表示实际轰炸到的岛屿的面积。
 

[align=left]Sample Input[/align]

0 0 2000
100 0
100

4
1900 100
2000 100
2000 -100
1900 -100

 

[align=left]Sample Output[/align]

15707.96

多边形与园面积相交主要思想就是把多边形拆成一个一个三角形,计算三角形与园面积相交的结果,然后累加。

三角形与圆面积的计算分了四种情况,具体看这里:http://www.cnblogs.com/lxglbk/archive/2012/08/12/2634192.html

具体代码:

/* ***********************************************
Author :_rabbit
Created Time :2014/5/7 10:36:31
File Name :F.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x){
if(fabs(x)<eps)return 0;
return x>0?1:-1;
}
struct Point{
double x,y;
Point(double _x=0,double _y=0){
x=_x;y=_y;
}
};
Point operator + (Point a,Point b){
return Point(a.x+b.x,a.y+b.y);
}
Point operator - (Point a,Point &b){
return Point(a.x-b.x,a.y-b.y);
}
Point operator * (Point a,double p){
return Point(a.x*p,a.y*p);
}
Point operator / (Point a,double p){
return Point(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);
}
bool operator == (const Point &a,const Point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
double Length(Point a){
return sqrt(Dot(a,a));
}
double Angle(Point a,Point b){
return acos(Dot(a,b)/Length(a)/Length(b));
}
double angle(Point a){
return atan2(a.y,a.x);
}
double Cross(Point a,Point b){
return a.x*b.y-a.y*b.x;
}
Point vecunit(Point a){
return a/Length(a);
}
Point Normal(Point a){
return Point(-a.y,a.x)/Length(a);
}
Point Rotate(Point a,double rad){
return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
bool OnSegment(Point p,Point a1,Point a2){
return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<=0;
}
Point GetLineIntersection(Point p,Point v,Point q,Point w){
Point u=p-q;
double t=Cross(w,u)/Cross(v,w);
return p+v*t;
}
struct Line{
Point p,v;
double ang;
Line(){}
Line(Point _p,Point _v){
p=_p;v=_v;ang=atan2(v.y,v.x);
}
bool operator < (const Line &L) const {
return ang<L.ang;
}
Point point(double a){
return p+(v*a);
}
};
Point GetLineIntersection(Line a,Line b){
return GetLineIntersection(a.p,a.v,b.p,b.v);
}
struct Circle
{
Point c;
double r;
Circle(){}
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);
}
};

bool InCircle(Point x,Circle c){
return dcmp(c.r-Length(c.c-x))>=0;
}
bool OnCircle(Point x,Circle c){
return dcmp(c.r-Length(c.c-x))==0;
}
int getSegCircleIntersection(Line L,Circle C,Point *sol){
Point nor=Normal(L.v);
Line p1=Line(C.c,nor);
Point ip=GetLineIntersection(p1,L);
double dis=Length(ip-C.c);
if(dcmp(dis-C.r)>0)return 0;
Point dxy=vecunit(L.v)*sqrt(C.r*C.r-dis*dis);
int ret=0;
sol[ret]=ip+dxy;
if(OnSegment(sol[ret],L.p,L.point(1)))ret++;
sol[ret]=ip-dxy;
if(OnSegment(sol[ret],L.p,L.point(1)))ret++;
return ret;
}
double SegCircleArea(Circle C,Point a,Point b){
double a1=angle(a-C.c);
double a2=angle(b-C.c);
double da=fabs(a1-a2);
if(da>pi)da=pi*2-da;
return dcmp(Cross(b-C.c,a-C.c))*da*C.r*C.r/2.0;
}
double PolyCircleArea(Circle C,Point *p,int n){
double ret=0;
Point sol[2];
p
=p[0];
for(int i=0;i<n;i++){
double t1,t2;
int cnt=getSegCircleIntersection(Line(p[i],p[i+1]-p[i]),C,sol);
if(cnt==0){
if(!InCircle(p[i],C)||!InCircle(p[i+1],C))ret+=SegCircleArea(C,p[i],p[i+1]);
else ret+=Cross(p[i+1]-C.c,p[i]-C.c)/2;
}
if(cnt==1){
if(InCircle(p[i],C)&&!InCircle(p[i+1],C))ret+=Cross(sol[0]-C.c,p[i]-C.c)/2,ret+=SegCircleArea(C,sol[0],p[i+1]);
else ret+=SegCircleArea(C,p[i],sol[0]),ret+=Cross(p[i+1]-C.c,sol[0]-C.c)/2;
}
if(cnt==2){
if((p[i]<p[i+1])^(sol[0]<sol[1]))swap(sol[0],sol[1]);
ret+=SegCircleArea(C,p[i],sol[0]);
ret+=Cross(sol[1]-C.c,sol[0]-C.c)/2;
ret+=SegCircleArea(C,sol[1],p[i+1]);
}
}
return fabs(ret);
}
Point p[200000];
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
Point a,b;
double h,R;
int n;
while(~scanf("%lf%lf%lf",&a.x,&a.y,&h)){
scanf("%lf%lf%lf%d",&b.x,&b.y,&R,&n);
for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
double t=sqrt(h/5);
Point g=Point(a.x+b.x*t,a.y+b.y*t);
Circle h=Circle(g,R);
double ans=PolyCircleArea(h,p,n);
printf("%.2lf\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: