POJ3348-Cows-求凸包面积
题意:求给定的n个坐标形成的凸包面积
套公式即可。
从而引入凸包
思路:
本题利用叉乘求面积(选取凸包上的一个点作为基点,然后把多边形分成许多的三角形,然后用叉积去算三角形面积即可)
求解凸包用到的是Andrew算法,Graham算法的变种,速度更快稳定性也更好。
两种算法的复杂度均为O(nlogn),若输入有序的话时间复杂度就均为O(n)
下面介绍Andrew算法:
Andrew算法执行步骤:
1、将所有的点按照横坐标从小到大进行排序,横坐标相同则按纵坐标从小到大排;
2、将P[0]和P[1]加入凸包,然后从P[2]开始判断,判断方式同Graham算法中的判断一致;
3、将所有的点扫描一遍以后,我们便可以得到一个“下凸包”(为什么?画个图就懂了--横坐标不会减小);
4、同理,我们从P[n-2]开始(P[n-1]已经判过了),反着扫描一遍,便可以得到一个“上凸包”;
5、将两个“半凸包”合在一起就是一个完整的凸包,注意的是由于起点P[0]在正着扫描和反着扫描时都会将其加入凸包,故需要将最后一个点(P[0])去掉才为最终结果。
AC代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<string.h> 5 6 using namespace std; 7 typedef long long ll; 8 #define inf 0x3f3f3f3f 9 const int N=10020; 10 11 struct node 12 { 13 double x,y; 14 }p[N],st[N]; 15 int n; 16 17 double cross(node a,node b,node c) 18 { 19 return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); 20 } 21 22 int cmp(node a,node b) 23 { 24 if(a.x!=b.x) 25 return a.x<b.x; 26 return a.y<b.y; 27 } 28 29 int Andrew() 30 { 31 sort(p,p+n,cmp); 32 int x=0; 33 for(int i=0;i<n;i++) 34 { 35 while(x>1&&cross(st[x-2],st[x-1],p[i])<=0) 36 x--; 37 st[x++]=p[i]; 38 } 39 int k=x; 40 for(int i=n-2;i>=0;i--) 41 { 42 while(x>k&&cross(st[x-2],st[x-1],p[i])<=0) 43 x--; 44 st[x++]=p[i]; 45 } 46 return x-1; 47 } 48 49 int main() 50 { 51 while(~scanf("%d",&n)) 52 { 53 memset(st,0,sizeof(st)); 54 for(int i=0;i<n;i++) 55 scanf("%lf %lf",&p[i].x,&p[i].y); 56 int ans=0; 57 int x=Andrew(); 58 for(int i=1;i<x;i++) 59 ans+=cross(st[0],st[i],st[i+1]); 60 printf("%d\n",ans/100);//ans/2/50 61 } 62 return 0; 63 }