计算机几何

几何

凸包面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;

const int maxn = 1005;
double area = 0.0;
struct node
{
int x;
int y;
} a[maxn];

bool cmp(node a, node b)
{
if (a.x != b.x)
return a.x < b.x;
return a.y < b.y;
}

bool direction(node a, node b, node c)
{
// 向量ab的坐标
int x1 = b.x - a.x;
int y1 = b.y - a.y;
// 向量ac的坐标
int x2 = c.x - a.x;
int y2 = c.y - a.y;
if (x1 * y2 - x2 * y1 > 0)
return true; // ab在ac的顺时针方向
return false; // 在逆时针方向
}

// 求任意三个点连线围成的三角行面积
double getArea(node a, node b, node c)
{
// 三角行的面积 = 三阶行列式的一半
return fabs(0.5 * (a.x * b.y + b.x * c.y + c.x * a.y -
a.x * c.y - b.x * a.y - c.x * b.y));
}

// 计算上下凸包的面积
void caculate(bool flag, int left, int right)
{
double temp = -1.0;
int k = 0; // 面积最大的那个点的横坐标
for (int i = left + 1; i <= right - 1; i++)
{
if (direction(a[left], a[right], a[i]) != flag)
{
continue;
}
if (temp < getArea(a[left], a[right], a[i]))
{
temp = getArea(a[left], a[right], a[i]);
k = i;
}
}
if (k == 0)
return;
area += temp;
caculate(flag, left, k);
caculate(flag, k, right);
}

int main()
{
int t;
cin >> t;
while (t--)
{
area = 0.0;
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].x >> a[i].y;
}
sort(a + 1, a + n + 1, cmp);
caculate(true, 1, n);
caculate(false, 1, n);
printf("%.1lf\n", area);
}

return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!