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 }