개발일지

Algorithm - Convex Hull (블록 껍질) 본문

Algorithm (알고리즘)

Algorithm - Convex Hull (블록 껍질)

강태종 2020. 9. 6. 19:45

개념

Convex Hull이란 2차원 평면 위에 점들이 있을 때 최소한의 정점으로 다른 정점들을 감싸는 알고리즘이다.

Convex Hull

대표적인 알고리즘으로 Graham's Scan(그라함 스캔)이 있다.

Graham's Scan


작동원리

1. 정점을 반 시계 or 시계 방향으로 정렬한다.

2. Graham's Scan 알고리즘을 이용한다.


시간복잡도

정점을 정렬할 때 -> nlogn, Graham's Scan할 때 -> n

-> O(nlogn)


문제

1708 블록 껍질

www.acmicpc.net/problem/1708

 

1708번: 볼록 껍질

첫째 줄에 점의 개수 N(3 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에 걸쳐 각 점의 x좌표와 y좌표가 빈 칸을 사이에 두고 주어진다. 주어지는 모든 점의 좌표는 다르다고 가정해도 좋다. x��

www.acmicpc.net


코드

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

constexpr int COUNTER_CLOCK_WISE = 1;
constexpr int CLOCK_WISE = -1;
constexpr int STRAIGHT = 0;

class Point {
public:
    long long x, y;

    explicit Point(long long x = 0L, long long y = 0L) : x(x), y(y) {

    }
};

int ccw(Point p1, Point p2, Point p3) {
    long long l = p1.x * p2.y + p2.x * p3.y + p3.x * p1.y;
    long long r = p2.x * p1.y + p3.x * p2.y + p1.x * p3.y;

    if (l - r > 0) {
        return COUNTER_CLOCK_WISE;
    }else if(l - r < 0) {
        return CLOCK_WISE;
    } else {
        return STRAIGHT;
    }
}

int n;
vector<Point> ve;

bool Ascending(const Point &p1, const Point &p2) {
    if (p1.x != p2.x) {
        return p1.x < p2.x;
    }

    return p1.y < p2.y;
}

bool CounterClockWiseSort(const Point &p1, const Point &p2) {
    int result = ccw(ve[0], p1, p2);

    if (result != STRAIGHT) {
        return result == COUNTER_CLOCK_WISE;
    }

    return Ascending(p1, p2);
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr);

    cin >> n;
    for (int i = 0;i < n;++i) {
        long long x, y;
        cin >> x >> y;

        ve.emplace_back(x, y);
    }

    sort(ve.begin(), ve.end(), Ascending);
    sort(ve.begin() + 1, ve.end(), CounterClockWiseSort);

    int next = 2;
    stack<int> st; st.push(0); st.push(1);
    while (next < n) {
        while (st.size() >= 2) {
            int v1 = next;
            int v2 = st.top();st.pop();
            int v3 = st.top();

            if (ccw(ve[v3], ve[v2], ve[v1]) == COUNTER_CLOCK_WISE) {
                st.push(v2);
                break;
            }
        }

        st.push(next++);
    }

    cout << st.size() << "\n";
}

 

'Algorithm (알고리즘)' 카테고리의 다른 글

Algorithm - Cut Edge (단절선)  (0) 2020.09.17
Algorithm - Cut Vertex(단절점)  (0) 2020.09.17
Algorithm - Topological Sort (위상정렬)  (0) 2020.09.08
Algorithm - LCA (최소 공통 조상)  (0) 2020.09.07
Algorithm - CCW  (0) 2020.09.06
Comments