Geometry - GitDeveloperKim/DreamEach GitHub Wiki

Convex Hull

  • 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;
    }
}

์ถœ์ฒ˜

  • ์ปจ๋ฐฑ์Šค ํ—์ด๋ž€?
  • reference
  1. list[] ์— ์žˆ๋Š” ์ ๋“ค ์ค‘ ๊ฐ€์žฅ ์ž‘์€ ๊ฒƒ์„ ์ฐพ์•„์„œ ๊ธฐ์ค€์ ์œผ๋กœ ์„ ์ •ํ•œ๋‹ค. (๋ณดํ†ต y๊ธฐ์ค€)
  2. ๊ธฐ์ค€์  ๊ธฐ์ค€์œผ๋กœ ๊ฐ๊ฐ์˜ ์ ๋“ค์„ ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์œผ๋กœ ๊ธฐ์ค€์ ๊ณผ ๊ฐ๋„ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌํ•œ๋‹ค.
  3. ์ ๋“ค์„ ํ•˜๋‚˜์”ฉ ๋ณด๋ฉด์„œ ๋ณผ๋ก๊ป์งˆ์— ํฌํ•จ์‹œํ‚ฌ์ง€ ๋ง์ง€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
  4. ์Šคํƒ์„ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ , ์ด ์Šคํƒ์—๋Š” ์ ์˜ ๋ฒˆํ˜ธ๋ฅผ ๋„ฃ์–ด์ฃผ๋Š”๋ฐ ์Šคํƒ ์‚ฌ์ด์ฆˆ๊ฐ€ ํ•œ๊ฐœ๋ฐ–์— ์—†์œผ๋ฉด ์ผ๋‹จ ์ง€๊ธˆ ์žก๊ณ  ์žˆ๋Š” ์ ์„ ๋„ฃ๋Š”๋‹ค.
  5. ์Šคํƒ์— ์ ์ด ๋‘ ๊ฐœ ์ด์ƒ์ด๋ฉด ๋น„๊ต๋ฅผ ํ•œ๋‹ค.
  6. ์  ๋‘๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‹ค๋ฅธ ์ ์„ ๋ดค์„ ๋•Œ CCW๋ฅผ ํ•˜๋Š”๋ฐ, ์ด ๋•Œ ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์— ์žˆ์œผ๋ฉด ๋งŒ์กฑํ•˜๋ฏ€๋กœ ์Šคํƒ์— ๋„ฃ์–ด์ค€๋‹ค.
  7. ๊ทธ๋ฆฌ๊ณ ๋‚˜์„œ ๋˜ ์Šคํƒ์˜ ๋‘๊ฐœ๋ฅผ ๋นผ์„œ ๋‘ ์  ๊ธฐ์ค€์œผ๋กœ ๋‹ค์Œ ์ ์„ CCW ํ•œ๋‹ค.
  8. ๋งŒ์•ฝ ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์— ์—†๋‹ค๋ฉด ์˜ค๋ชฉํ•˜๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿด ๊ฒฝ์šฐ์—๋Š” ์Šคํƒ์—์„œ ๋นผ์ค€๋‹ค.
  9. ์ด๋ ‡๊ฒŒ ๊ณ„์† ๋ฐ˜๋ณตํ•ด์ค€๋‹ค.

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;
    }
}

monoton chain?!


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;
        }
    }
}

์ถœ์ฒ˜

โš ๏ธ **GitHub.com Fallback** โš ๏ธ