1708 - 볼록 껍질
info
- 문제 보기: 1708 - 볼록 껍질
- 소요 시간: 54분 13초
- 풀이 언어:
java - 체감 난이도: 3️⃣~4️⃣
- 리뷰 횟수: ✅
풀이 키워드
스포주의
수학
풀이 코드
info
- 메모리: 27464 KB
- 시간: 460 ms
import java.util.*;
import java.io.*;
public class Main
{
static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static int n;
static long[][] dot;
static int ccw(long[] a, long[] b, long[] c) {
long ax = a[0];
long ay = a[1];
long bx = b[0];
long by = b[1];
long cx = c[0];
long cy = c[1];
// cross product
long v = (ax*by + bx*cy + cx*ay) - (ay*bx + by*cx + cy*ax);
if (v > 0) return 1; // counter-clockwise
else if (v < 0) return -1; // clockwise
else return 0; // in-line
}
static long dist(long[] a, long[] b) {
return (b[0]-a[0])*(b[0]-a[0]) + (b[1]-a[1])*(b[1]-a[1]);
}
public static void main(String[] args) throws IOException {
n = readInt();
dot = new long[n][2];
for (int i = 0; i < n; ++i) {
dot[i][0] = readInt(); // x
dot[i][1] = readInt(); // y
}
// graham scan
// 1. find minimum y(x if same) dot
int mndx = 0;
for (int i = 1; i < n; ++i) {
if (dot[i][1] < dot[mndx][1]) mndx = i;
else if (dot[i][1] == dot[mndx][1]) {
if (dot[i][0] < dot[mndx][0]) mndx = i;
}
}
// swap
long[] tmp = dot[0];
dot[0] = dot[mndx];
dot[mndx] = tmp;
// 2. sort by ccw from idx 1 to n-1
Arrays.sort(dot, 1, n, (a, b) -> {
int v = ccw(dot[0], a, b);
if (v != 0) return v*-1; // reverse sign
// sort by distance asc if in-line
long d1 = dist(dot[0], a);
long d2 = dist(dot[0], b);
return Long.compare(d1, d2);
});
// 3. scan
Deque<Integer> stack = new ArrayDeque<>();
stack.push(0);
stack.push(1);
for (int idx = 2; idx < n; ++idx) {
while (stack.size() >= 2) {
int bdx = stack.pop();
int adx = stack.peek();
if (ccw(dot[adx], dot[bdx], dot[idx]) > 0) {
stack.push(bdx);
break;
}
}
stack.push(idx);
}
System.out.println(stack.size());
}
static int readInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}
풀이 해설
기본적인 Convex Hull 알고리즘으로 풀이할 수 있는 기하학 문제이다.