- CCW (Counter Clockwise)
- ์ธ์ p1(x1,y1), p2(x2,y2), p3(x3,y3) ์ด ์์ ๋ ๊ฐ๋ฅํ ๊ฒฝ์ฐ์ ์ 3๊ฐ์ง
- ์๊ณ ๋ฐฉํฅ -1, ์ผ์ง์ 0, ๋ฐ์๊ณ ๋ฐฉํฅ 1
- ์ธ์ ๊ณต์ : 2S = (x2-x1)(y3-y1) - (y2-y1)(x3-x1)
- s > 0 : ๋ฐ์๊ณ ๋ฐฉํฅ
- s = 0 : ์ผ์ง์
- s < 0 : ์๊ณ ๋ฐฉํฅ
int ccw(int x1, int y1, int x2, int y2, int x3, int y3) {
int temp = x1*y2+x2*y3+x3*y1;
temp = temp - y1*x2-y2*x3-y3*x1;
if (temp > 0) {
return 1;
} else if (temp < 0) {
return -1;
} else {
return 0;
}
}
์ถ์ฒ
- list[] ์ ์๋ ์ ๋ค ์ค ๊ฐ์ฅ ์์ ๊ฒ์ ์ฐพ์์ ๊ธฐ์ค์ ์ผ๋ก ์ ์ ํ๋ค. (๋ณดํต y๊ธฐ์ค)
- ๊ธฐ์ค์ ๊ธฐ์ค์ผ๋ก ๊ฐ๊ฐ์ ์ ๋ค์ ๋ฐ์๊ณ ๋ฐฉํฅ์ผ๋ก ๊ธฐ์ค์ ๊ณผ ๊ฐ๋ ์์๋๋ก ์ ๋ ฌํ๋ค.
- ์ ๋ค์ ํ๋์ฉ ๋ณด๋ฉด์ ๋ณผ๋ก๊ป์ง์ ํฌํจ์ํฌ์ง ๋ง์ง๋ฅผ ๊ฒฐ์ ํ๋ค.
- ์คํ์ ํ๋ ๋ง๋ค๊ณ , ์ด ์คํ์๋ ์ ์ ๋ฒํธ๋ฅผ ๋ฃ์ด์ฃผ๋๋ฐ ์คํ ์ฌ์ด์ฆ๊ฐ ํ๊ฐ๋ฐ์ ์์ผ๋ฉด ์ผ๋จ ์ง๊ธ ์ก๊ณ ์๋ ์ ์ ๋ฃ๋๋ค.
- ์คํ์ ์ ์ด ๋ ๊ฐ ์ด์์ด๋ฉด ๋น๊ต๋ฅผ ํ๋ค.
- ์ ๋๊ฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ค๋ฅธ ์ ์ ๋ดค์ ๋ CCW๋ฅผ ํ๋๋ฐ, ์ด ๋ ๋ฐ์๊ณ ๋ฐฉํฅ์ ์์ผ๋ฉด ๋ง์กฑํ๋ฏ๋ก ์คํ์ ๋ฃ์ด์ค๋ค.
- ๊ทธ๋ฆฌ๊ณ ๋์ ๋ ์คํ์ ๋๊ฐ๋ฅผ ๋นผ์ ๋ ์ ๊ธฐ์ค์ผ๋ก ๋ค์ ์ ์ CCW ํ๋ค.
- ๋ง์ฝ ๋ฐ์๊ณ ๋ฐฉํฅ์ ์๋ค๋ฉด ์ค๋ชฉํ๋ค๋ ์๋ฏธ์ด๋ฏ๋ก ๋ง์กฑํ์ง ์๋๋ค. ๋ฐ๋ผ์ ์ด๋ด ๊ฒฝ์ฐ์๋ ์คํ์์ ๋นผ์ค๋ค.
- ์ด๋ ๊ฒ ๊ณ์ ๋ฐ๋ณตํด์ค๋ค.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;
import java.util.StringTokenizer;
class Hull{
int x, y;
Hull(int x, int y){
this.x = x;
this.y = y;
}
}
public class temp {
static int N;
static Hull list[];
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
list = new Hull[N+1];
for(int i=1; i<=N; i++){
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
list[i] = new Hull(a, b);
}
// 1. ๊ธฐ์ค์ ์ ์
for(int i=1; i<=N; i++){
if(list[1].y > list[i].y || list[1].y == list[i].y && list[1].x > list[i].x){
Hull temp = list[1];
list[1] = list[i];
list[i] = temp;
}
}
// 2. ๊ธฐ์ค์ ๊ธฐ์ค์ผ๋ก ๋ฐ์๊ณ๋ฐฉํฅ์ผ๋ก ์ ๋ ฌ
Arrays.sort(list, 2, N+1, new Comparator() {
@Override
public int compare(Hull a, Hull b) {
// TODO Auto-generated method stub
int v = ccw(new Hull(list[1].x, list[1].y), a, b);
if( v > 0) return -1;
if(v<0) return 1;
return (Math.abs(a.x) + a.y) - (Math.abs(b.x) + b.y);
}
});
// 3. stack
Stack stack = new Stack<>();
stack.push(1);
for(int i=2; i<=N; i++){
while(stack.size() > 1 && ccw(list[stack.get(stack.size()-2)], list[stack.peek()], list[i]) <=0 ){
stack.pop();
}
stack.add(i);
}
bw.write(stack.size() + "\n");
bw.flush();
}
protected static int ccw(Hull A, Hull B, Hull C) {
long cal = 0;
cal = (long)(B.x - A.x) * (C.y - A.y) - (long)(C.x-A.x) * (B.y-A.y);
if(cal > 0) return 1;
else if (cal< 0) return -1;
else return 0;
}
}
import java.io.*;
import java.util.*;
class Point {
long x;
long y;
Point(long x, long y) {
this.x = x;
this.y = y;
}
}
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
ArrayList points = new ArrayList<>();
for (int i = 0; i < n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
String belong = st.nextToken();
if (belong.equals("Y")) { // Y์ธ ๊ฒ๋ง ๋ณผ๋ก ๊ป์ง
points.add(new Point(x, y));
}
}
Stack result = grahamScan(points);
bw.write(result.size() + "\n");
for (int i = 0; i < result.size(); i++) {
bw.write(result.get(i).x + " " + result.get(i).y + "\n");
}
br.close();
bw.flush();
bw.close();
}
static Stack grahamScan(ArrayList input) throws IOException {
// ๋ชจ๋ ์ ๋ค์ x ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ธฐ
input.sort(new Comparator() {
@Override
public int compare(Point p1, Point p2) { // return 1์ด๋ฉด ์๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค
if (p1.x > p2.x) {
return 1;
} else if (p1.x == p2.x) {
if (p1.y > p2.y) {
return 1;
}
}
return -1;
}
});
Stack lower = new Stack<>(); // ์๋ ๊ป์ง
Stack upper = new Stack<>(); // ์ ๊ป์ง
// ์๋ ๊ป์ง ๊ณ์ฐ
for (int i = 0; i < input.size(); i++) {
while (lower.size() > 1 && (ccw(lower.get(lower.size() - 2), lower.get(lower.size() - 1), input.get(i)) < 0)) { // first, second, next
lower.pop();
}
lower.add(input.get(i));
}
// ์ ๊ป์ง ๊ณ์ฐ
for (int i = input.size() - 1; i >= 0; i--) {
while (upper.size() > 1 && (ccw(upper.get(upper.size() - 2), upper.get(upper.size() - 1), input.get(i)) < 0)) { // first, second, next
upper.pop();
}
upper.add(input.get(i));
}
lower.pop(); // ์ค๋ณต ์ ๊ฑฐ
upper.pop();
lower.addAll(upper);
return lower;
}
static int ccw(Point p1, Point p2, Point p3) {
long result = (p1.x * p2.y + p2.x * p3.y + p3.x * p1.y) - (p2.x * p1.y + p3.x * p2.y + p1.x * p3.y);
if (result > 0) { // ๋ฐ์๊ณ ๋ฐฉํฅ
return 1;
} else if (result < 0) { // ์๊ณ ๋ฐฉํฅ
return -1;
} else {
return 0;
}
}
}
์ถ์ฒ