Skip to content

Commit 4b6c85a

Browse files
authored
Graham扫描法求凸包(附CodeVS - 1298 凸包周长代码)
1 parent 21d436c commit 4b6c85a

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed

Graham-Scan.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#include <cstdio>
2+
#include <cmath>
3+
4+
#define POINT_COUNT 100000
5+
6+
using namespace std;
7+
8+
struct point
9+
{
10+
int x, y;
11+
}P[POINT_COUNT];
12+
13+
struct segment
14+
{
15+
point begin, end;
16+
}D[POINT_COUNT];
17+
18+
int S[POINT_COUNT], sp = 0;
19+
20+
int n;
21+
22+
void push(int x)
23+
{
24+
S[sp++] = x;
25+
}
26+
27+
int pop()
28+
{
29+
return S[--sp];
30+
}
31+
32+
int top()
33+
{
34+
return S[sp - 1];
35+
}
36+
37+
int subtop()
38+
{
39+
return S[sp - 2];
40+
}
41+
42+
int direction(segment &base, segment &s)
43+
{
44+
return (s.end.x - s.begin.x) * (base.end.y - base.begin.y) - (base.end.x - base.begin.x) * (s.end.y - s.begin.y);
45+
}
46+
47+
double distance(point &x, point &y)
48+
{
49+
return sqrt(pow(x.x - y.x, 2) + pow(x.y - y.y, 2));
50+
}
51+
52+
void qsort(int l, int r)
53+
{
54+
if (l < r)
55+
{
56+
segment x = D[r];
57+
int j = l - 1;
58+
for (int i = l; i <= r; i++)
59+
{
60+
if (direction(x, D[i]) >= 0)
61+
{
62+
j++;
63+
segment temps = D[i];
64+
D[i] = D[j];
65+
D[j] = temps;
66+
point tempp = P[i];
67+
P[i] = P[j];
68+
P[j] = tempp;
69+
}
70+
}
71+
qsort(l, j - 1);
72+
qsort(j + 1, r);
73+
}
74+
}
75+
76+
int main()
77+
{
78+
scanf("%d", &n);
79+
for (int i = 0; i < n; i++)
80+
{
81+
scanf("%d%d", &P[i].x, &P[i].y);
82+
}
83+
int p0 = 0;
84+
for (int i = 1; i < n; i++)
85+
{
86+
if (P[i].x < P[p0].x)
87+
{
88+
p0 = i;
89+
}
90+
else if (P[i].x == P[p0].x)
91+
{
92+
if (P[i].y < P[p0].y)
93+
{
94+
p0 = i;
95+
}
96+
}
97+
}
98+
point temp = P[p0];
99+
P[p0] = P[0];
100+
P[0] = temp;
101+
for (int i = 1; i < n; i++)
102+
{
103+
D[i].begin = P[0];
104+
D[i].end = P[i];
105+
}
106+
qsort(1, n - 1);
107+
push(0);
108+
for (int i = 1; i < n; i++)
109+
{
110+
if (sp >= 2)
111+
{
112+
if (direction(D[i], D[top()]) == 0)
113+
{
114+
if (P[i].x > P[top()].x)
115+
{
116+
pop();
117+
}
118+
else
119+
{
120+
continue;
121+
}
122+
}
123+
int dir;
124+
do
125+
{
126+
segment base, toward;
127+
base.begin = P[subtop()];
128+
base.end = P[top()];
129+
toward.begin = P[top()];
130+
toward.end = P[i];
131+
dir = direction(base, toward);
132+
if (dir > 0)
133+
{
134+
pop();
135+
}
136+
} while (dir > 0);
137+
}
138+
push(i);
139+
}
140+
double res = 0;
141+
for (int i = 1; i < sp; i++)
142+
{
143+
res += distance(P[S[i]], P[S[i - 1]]);
144+
}
145+
res += distance(P[S[sp - 1]], P[0]);
146+
printf("%.1lf", res);
147+
148+
return 0;
149+
}

0 commit comments

Comments
 (0)