凸包 Graham扫描法

View Code
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include <conio.h>
  5 #define N 20
  6 #define inf 1e-6 // 10的6次方
  7 
  8 typedef struct
  9 {
 10     int x;
 11     int y;
 12 }point;
 13 point points[N]; //点集
 14 point chs[N]; //
 15 int sp; //栈顶指针
 16 
 17 //计算两点之间距离
 18 double dis(point a, point b)
 19 {
 20     return sqrt((a.x - b.x) * (a.x - b.x) * 1.0 + (a.y - b.y) * (a.y - b.y));
 21 }
 22 
 23 //通过矢量叉积求极角关系(p0p1)(p0p2)        a × b = x1*y2 - x2*y1
 24 //k > 0 ,p0p1在p0p2顺时针方向上
 25 double multi(point p0, point p1, point p2) 
 26 {
 27     return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
 28 }
 29 
 30 int cmp(const void *p, const void *q)
 31 {
 32     point a = *(point *)p;
 33     point b = *(point *)q;
 34     double k = multi(points[0], a, b);
 35     if(k < -inf)
 36         return 1; 
 37     else if(fabs(k) < inf && (dis(a, points[0]) - dis(b, points[0])) > inf) //两点在同一直线上的话,用最近的
 38         return 1;
 39     else return -1;
 40 }
 41 
 42 void convex_hull(int n)
 43 {
 44     int i, k, d;
 45     int miny = points[0].y, index = 0;
 46     for(i=1; i<n; i++) //找最左下顶点
 47     {
 48         if(points[i].y < miny) //找到y坐标最小的点
 49         { 
 50             miny = points[i].y;
 51             index = i;
 52         }
 53         else if(points[i].y == miny && points[i].x < points[index].x) //相同的话找到x最小的
 54         {
 55             index = i;
 56         }
 57     }
 58     //把最左下顶点放到第一个
 59     point temp;
 60     temp = points[index];
 61     points[index] = points[0];
 62     points[0] = temp;
 63     qsort(points+1, n-1, sizeof(points[0]), cmp); //p[1:n-1]按相对p[0]的极角从小到大排序
 64     chs[0] = points[n-1];
 65     chs[1] = points[0];
 66     sp = 1;
 67     k = 1;
 68     while(k <= n-1)
 69     {
 70         double d = multi(chs[sp], chs[sp-1], points[k]);
 71         if(d <= 0)
 72         {
 73             sp++;
 74             chs[sp] = points[k];
 75             k++;
 76         }
 77         else sp--;
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     int i, j, n;
 84     float sum, area;
 85     //freopen("in.txt", "r", stdin);
 86     scanf("%d", &n);
 87     for(i=0; i<n; i++)
 88         scanf("%d%d", &points[i].x, &points[i].y);
 89 
 90     convex_hull(n);
 91 
 92     for(i=0; i<=sp; i++)
 93         printf("(%d, %d) \n ", chs[i].x, chs[i].y);
 94     sum = 0;
 95     for(i=1; i<=sp; i++) //求周长
 96         sum += dis(chs[i-1], chs[i]);
 97     sum += dis(chs[0], chs[sp]);
 98     printf("周长:%f\n", sum);
 99     area = 0;
100     for(i=1; i<sp; i++) //求面积
101     {
102         double k = multi(chs[0], chs[i], chs[i+1]); //三角形面积是向量叉积的1/2
103         area += k;
104     }
105     area = fabs(area) / 2;
106     printf("面积:%f\n", area);
107     getch();
108     return 0;
109 }

 

posted @ 2012-12-15 16:52  pc....  阅读(107)  评论(0)    收藏  举报