Convex Hull μ΄λ?
2μ°¨μ νλ©΄μ μ’νλ€μ΄ μ£Όμ΄μ‘μλ κ°μ₯ λ°κΉ₯μͺ½μ μ’νλ€λ§ μ°κ²°νμ¬ λ€κ°νμ λ§λλ μκ³ λ¦¬μ¦
κ²°κ³Όμ μΌλ‘λ μ»¨λ²‘μ€ νμ ꡬμ±νλ μ λ€μ μ’νλ₯Ό μ»μ μ μλ€.
λͺ¨λ μ’νλ€μ ꡬν΄μ§ κ²½κ³μ μμ μ‘΄μ¬νλ€. κ·Έλ κΈ°μ μ λ€μ΄ μ°¨μ§νλ μ΅μ μμμ ꡬν μ μλ€.
Graham Scan Algorithm
- λ¨Όμ μ λ€μ yμ’ν κΈ°μ€, κ°μΌλ©΄ xμ’ν κΈ°μ€μΌλ‘ μ λ ¬νλ€. (μ€λ¦μ°¨μ) -> μ΄λμμ μμ(κ°μ₯ μλ)νλμ§
- κ°μ₯ μλμ μλ μ μ κΈ°μ€μΌλ‘, λλ¨Έμ§ μ λ€μ κ°λ κΈ°μ€μΌλ‘ μ λ ¬νλ€.
(κ°λλ κΈ°μ€μ μμ λ°μκ³λ°©ν₯(κ°λ λμ)μΈμ§ νμΈ. CCW(Counter Clock Wise) μ¬μ©)
CCW νλ³: p->q->rμ νμ μκ³ μΆμλ (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x)
=> κ²°κ³Όκ° μμλ©΄ μκ³λ°©ν₯, μμλ©΄ λ°μκ³λ°©ν₯. μ λκ°μ κΊΎμ΄λ μ λ λνλ.
- κΈ°μ€μ λΆν° μμλλ‘ μ μ 보면μ μ€νμ λ£λ, μ€νμ μμ λ μ κ³Ό νμ¬ μ μ΄ μκ³ λ°©ν₯μ μ΄λ£¨λ©΄ pop νλ€.
- μ΄ κ³Όμ μ λ°λ³΅νμ¬, λ°μκ³ λ°©ν₯(CCW)λ§ μ μ§νλλ‘ νλ€.
- λͺ¨λ μ μ νμΈνμλ μ€νμ λ¨μμλ κ°μ΄ 컨벑μ€νμ΄ λλ€.
|
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
|
import java.util.*;
// μ μ νννλ ν΄λμ€
class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
// λ μ μ λ°©ν₯μ κ³μ°νλ λ©μλ (κ΅μ°¨ κ³±)
static int crossProduct(Point p, Point q, Point r) {
return (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
}
}
public class ConvexHull {
// κ·ΈλΌν¨ μ€μΊ μκ³ λ¦¬μ¦
public static List<Point> grahamScan(List<Point> points) {
if (points.size() < 3) {
return points;
}
// κΈ°μ€μ μ°ΎκΈ°
points.sort((p1, p2) -> (p1.y == p2.y) ? Integer.compare(p1.x, p2.x) : Integer.compare(p1.y, p2.y));
Point start = points.remove(0);
// κ°λκΈ°μ€ μ λ ¬
points.sort((p1, p2) -> {
int cp = Point.crossProduct(start, p1, p2);
if (cp == 0) {
return Integer.compare(distance(start, p1), distance(start, p2));
}
return cp > 0 ? -1 : 1;
});
// CCW νλ³λ‘ 컨벑μ€ν ꡬμ±νλμ§ νμΈ
Stack<Point> stack = new Stack<>();
stack.push(start);
stack.push(points.get(0));
for (int i = 1; i < points.size(); i++) {
while (stack.size() > 1 && Point.crossProduct(stack.get(stack.size() - 2), stack.peek(), points.get(i)) <= 0) {
stack.pop();
}
stack.push(points.get(i));
}
// μ€νμ λ¨μ μ λ€μ΄ μ»¨λ²‘μ€ νμ ꡬμ±νλ μ λ€
return new ArrayList<>(stack);
}
// λ μ κ°μ 거리
public static int distance(Point p1, Point p2) {
return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}
// μ΅μ’
μΆλ ₯
public static void printConvexHull(List<Point> convexHull) {
for (Point p : convexHull) {
System.out.println("(" + p.x + ", " + p.y + ")");
}
}
public static void main(String[] args) {
List<Point> points = new ArrayList<>();
points.add(new Point(0, 0));
points.add(new Point(1, 1));
points.add(new Point(2, 2));
points.add(new Point(4, 4));
points.add(new Point(0, 4));
points.add(new Point(1, 3));
points.add(new Point(3, 0));
List<Point> convexHull = grahamScan(points);
System.out.println("μ»¨λ²‘μ€ νμ ꡬμ±νλ μ λ€:");
printConvexHull(convexHull);
}
}
|
cs |
Comment