poj 3348 Cows 凸包模板题
2014-07-20 12:34
274 查看
题意:给定n个点,求这n个点构成的凸包的面积。
题解:典型的凸包模板题。先求m个点组成的凸包,然后根据凸包上的一个点,将凸包分成m-2个三角形,面积就是m-2个三角形之和。三角形面积等于两条边的叉积/2.
凸包求法讲解:
1)先将点根据横坐标从小到大排序
2)然后需要了解叉积。根据两个向量的叉积,我们可以知道一条边是在另一条边的上方还是下方。
3)接着先求凸包的下半部分。遍历点,每新进来一个点,跟已求得的凸包边比较,用叉积Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]),判断新加点是在已成凸包的外面还是里面。若是在外面,则删除所有边,当边向量和该边的起点到新增点所称向量叉积小于0,即删除在凸包内的点;将新增点加入到凸包数组中,形成新的凸包。以此类推得到凸包下边。
具体过程如下图所示,开始P1,P2,P3,P4,P6都在凸包数组中,现在加入P7;由于P4P6在P4P7上方(用叉积判),所以删除P6;由于P3P4在P3P7上方,所以删除P4;由于P2P3在P2P7下方,所以停止删除,将P7加入到凸包数组中,得到新的凸包数组P1,P2,P3,P7。接着遍历下一个点,如此反复,直到遍历所有的点,就可以得到凸包的下半部分了。
4)跟3)同理得到凸包上边,最后得到的数组就是凸包了。
代码:
题解:典型的凸包模板题。先求m个点组成的凸包,然后根据凸包上的一个点,将凸包分成m-2个三角形,面积就是m-2个三角形之和。三角形面积等于两条边的叉积/2.
凸包求法讲解:
1)先将点根据横坐标从小到大排序
2)然后需要了解叉积。根据两个向量的叉积,我们可以知道一条边是在另一条边的上方还是下方。
3)接着先求凸包的下半部分。遍历点,每新进来一个点,跟已求得的凸包边比较,用叉积Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]),判断新加点是在已成凸包的外面还是里面。若是在外面,则删除所有边,当边向量和该边的起点到新增点所称向量叉积小于0,即删除在凸包内的点;将新增点加入到凸包数组中,形成新的凸包。以此类推得到凸包下边。
具体过程如下图所示,开始P1,P2,P3,P4,P6都在凸包数组中,现在加入P7;由于P4P6在P4P7上方(用叉积判),所以删除P6;由于P3P4在P3P7上方,所以删除P4;由于P2P3在P2P7下方,所以停止删除,将P7加入到凸包数组中,得到新的凸包数组P1,P2,P3,P7。接着遍历下一个点,如此反复,直到遍历所有的点,就可以得到凸包的下半部分了。
4)跟3)同理得到凸包上边,最后得到的数组就是凸包了。
代码:
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> #include <map> #include <set> #include <queue> using namespace std; //基础点和向量运算 struct Point{ double x,y; Point(double x=0,double y=0):x(x),y(y){} }; typedef Point Vector; Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);} Vector operator - (Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);} Vector operator * (Vector A,double p){return Vector(A.x*p,A.y*p);} Vector operator / (Vector A,double p){return Vector(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); } const double eps=1e-10; int dcmp(double x)//判断正负,或者等于0 { if(fabs(x)<eps)return 0;else 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; } double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;}//点积 double Length(Vector A){return sqrt(Dot(A,A));}//OA长 double Angle(Vector A,Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}//OA和OB的夹角 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)//rad为弧度,旋转rad度 { return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); } Vector Normal(Vector A)//A的单位法向量,A不能为零向量 { double L=Length(A); return Vector(-A.y/L,A.x/L); } //点和直线 //P+tv表示一条直线,P为点,tv为方向向量 Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)//求直线交点,确保存在交点,即Cross(v,w)非0 { Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t; } double DistanceToLine(Point P,Point A,Point B)//P点到直线AB的距离 { Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Length(v1)); } double DistanceToSegment(Point P,Point A,Point B)//点P到线段AB的距离 { 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 a1,Point a2)//判断点是否在线段上(不包括端点) { return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0; } //多边型 double ConvexPolygonArea(Point* p,int n)//多边形面积,,点按顺序 { double area=0; for(int i=1;i<n-1;i++) area+=Cross(p[i]-p[0],p[i+1]-p[0]); return area/2; } int ConvexHull(Point *p,Point *ch,int n)//求凸包 { sort(p,p+n); int i,m=0,k; for(i=0;i<n;i++) { while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--; ch[m++]=p[i]; } k=m; for(i=n-2;i>=0;i--) { while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--; ch[m++]=p[i]; } if(n>1)m--; return m; } const int maxn=1e4+10; Point p[maxn],ch[maxn]; int n; int main() { while(scanf("%d",&n)!=EOF) { int i,j,k,m; for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); m=ConvexHull(p,ch,n); double ans; ans=ConvexPolygonArea(ch,m); printf("%d\n",(int)(ans/50.0)); } return 0; }
相关文章推荐
- POJ 3348 Cows (凸包模板)
- [POJ 3348] Cows 凸包模板
- POJ 3348 Cows | 凸包模板题
- POJ 3348 Cows 第一个凸包问题
- POJ 3348 Cows (凸包面积)
- POJ 3348 Cows 求凸包面积
- poj 3348 Cows 凸包 求多边形面积 计算几何 难度:0 Source:CCC207
- POJ 3348 Cows [凸包 面积]
- POJ 3348 || Cows(求凸包面积
- poj 3348 Cows (凸包面积)
- Poj 3348 Cows (凸包面积)
- POJ-3348 Cows 计算几何 求凸包 求多边形面积
- POJ 3348 Cows | 凸包——童年的回忆(误)
- poj 3348--Cows(凸包求面积)
- poj 3348:Cows(计算几何,求凸包面积)
- poj 3348 Cows(求凸包面积)
- POJ3348--cows--凸包
- Cows POJ - 3348 [凸包+面积]
- POJ 3348 Cows(凸包+多边形面积)
- POJ 3348 Cows(求凸包面积)