HDU 3060 多边形面积并
Area2
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1197 Accepted Submission(s): 278
Problem Description
小白近期又被空军特招为飞行员,參与一项实战演习。演习的内容还是轰炸某个岛屿(这次的岛屿非常大,非常大非常大非常大,大到炸弹怎么扔都能全然在岛屿上引爆),看来小白确实是飞行员的命。。。
这一次,小白扔的炸弹比較奇怪,爆炸的覆盖区域不是圆形,而是一个不规则的简单多边形,请你再次帮助小白,计算出炸到了多少面积。
须要注意的是,这次小白一共扔了两枚炸弹,可是两枚炸弹炸到的公共部分的面积仅仅能计算一次。
这一次,小白扔的炸弹比較奇怪,爆炸的覆盖区域不是圆形,而是一个不规则的简单多边形,请你再次帮助小白,计算出炸到了多少面积。
须要注意的是,这次小白一共扔了两枚炸弹,可是两枚炸弹炸到的公共部分的面积仅仅能计算一次。
Input
首先输入两个数n,m,分别代表两枚炸弹爆炸覆盖到的图形的顶点数;
接着输入n行,每行输入一个(x,y)坐标,代表第一枚炸弹爆炸范围图形的顶点(按顺势针或者逆时针给出)。
最后输入m行,每行输入一个(x',y')坐标,代表第二枚炸弹爆炸范围图形的顶点(按顺势针或者逆时针给出)。
(3<= n,m <= 500)
接着输入n行,每行输入一个(x,y)坐标,代表第一枚炸弹爆炸范围图形的顶点(按顺势针或者逆时针给出)。
最后输入m行,每行输入一个(x',y')坐标,代表第二枚炸弹爆炸范围图形的顶点(按顺势针或者逆时针给出)。
(3<= n,m <= 500)
Output
输出一个两位小数,表示实际轰炸到的岛屿的面积。
Sample Input
4 4 0 0 0 1 1 1 1 0 0.5 0.5 0.5 1.5 1.5 1.5 1.5 0.5
Sample Output
1.75
给定两个多边形,求面积并
把多边形分解成三角形,然后计算三角形的有向面积交。
代码:
/* *********************************************** Author :_rabbit Created Time :2014/5/4 15:03:55 File Name :20.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 10000000 #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 + (const Point &a,const Point &b){ return Point(a.x+b.x,a.y+b.y); } Point operator - (const Point &a,const Point &b){ return Point(a.x-b.x,a.y-b.y); } Point operator * (const Point &a,const double &p){ return Point(a.x*p,a.y*p); } Point operator / (const Point &a,const 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)); } double Area2(Point a,Point b,Point c){ return Length(Cross(b-a,c-a)); } 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; } }; bool OnLeft(const Line &L,const Point &p){ return dcmp(Cross(L.v,p-L.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; } Point GetLineIntersection(Line a,Line b){ return GetLineIntersection(a.p,a.v,b.p,b.v); } vector<Point> HPI(vector<Line> L){ int n=L.size(); sort(L.begin(),L.end());//将全部半平面依照极角排序。 int first,last; vector<Point> p(n); vector<Line> q(n); vector<Point> ans; q[first=last=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]=GetLineIntersection(q[last-1],q[last]);//计算队列顶部半平面交点。 } while(first<last&&!OnLeft(q[first],p[last-1]))last--;//删除队列顶部的无用半平面。 //cout<<first<<" "<<last<<endl; if(last-first<=1)return ans;//半平面退化 p[last]=GetLineIntersection(q[last],q[first]);//计算队列顶部与首部的交点。 for(int i=first;i<=last;i++)ans.push_back(p[i]);//将队列中的点复制。 return ans; } double PolyArea(vector<Point> p){ int n=p.size(); double ans=0; for(int i=1;i<n-1;i++) ans+=Cross(p[i]-p[0],p[i+1]-p[0]); return ans/2; } vector<Point> p1,p2; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int n,m; while(~scanf("%d%d",&n,&m)){ Point pp; p1.clear();p2.clear(); for(int i=0;i<n;i++)scanf("%lf%lf",&pp.x,&pp.y),p1.push_back(pp); for(int i=0;i<m;i++)scanf("%lf%lf",&pp.x,&pp.y),p2.push_back(pp); double ret1,ret2,ret=0; ret1=PolyArea(p1);if(dcmp(ret1)<0)reverse(p1.begin(),p1.end());ret+=fabs(ret1); ret2=PolyArea(p2);if(dcmp(ret2)<0)reverse(p2.begin(),p2.end());ret+=fabs(ret2); for(int i=1;i<n-1;i++) for(int j=1;j<m-1;j++){ vector<Point> s1,s2; s1.push_back(p1[0]); s1.push_back(p1[i]); s1.push_back(p1[i+1]); s2.push_back(p2[0]); s2.push_back(p2[j]); s2.push_back(p2[j+1]); double r1,r2; int flag1,flag2; r1=PolyArea(s1); if(dcmp(r1)>=0)flag1=1;else flag1=0; if(dcmp(r1)<0)reverse(s1.begin(),s1.end()); r2=PolyArea(s2); if(dcmp(r2)>=0)flag2=1;else flag2=0; if(dcmp(r2)<0)reverse(s2.begin(),s2.end()); vector<Line> L; for(int k=0;k<3;k++) L.push_back(Line(s1[k],s1[(k+1)%3]-s1[k])); for(int k=0;k<3;k++) L.push_back(Line(s2[k],s2[(k+1)%3]-s2[k])); vector<Point> tt=HPI(L); if(flag1==flag2)ret-=PolyArea(tt); else ret+=PolyArea(tt); } printf("%.2lf\n",ret); } return 0; }