BOJ - 볼록 껍질(1708)

문제(링크)
볼록 껍질(Convex Hull) 문제였습니다. 다음과 같이 진행합니다.

1. 기준점을 잡는다 -> y 가 가장 작은 점, y 가 같다면 x가 가장 작은 점
2. 점들을 반시계 방향으로 정렬한다. -> CCW를 이용해 기준점, p1, p2를 비교해
세 점이 반시계 방향이라면 True, 시계 방향이라면 False, 일직선일 때 p1이 기준점과
가까우면 True, 멀면 False을 리턴하는 Comparator로 정렬합니다.
3. 정렬된 점들에 대해 그라함 스캔 알고리즘을 사용합니다.

- 스택의 마지막 - 1 = first
- 스택의 마지막 = second
- 현재 비교하는 점 = next

위 세 점 first, second, next에 대해 CCW를 수행합니다.
CCW > 0  -> 스택에 next를 넣습니다.
CCW <= 0 -> 볼록껍질이 아니므로 이전의 first, second로 되돌리기 위해 스택을 pop 합니다.
(이 작업을 CCW > 0 이 될 때까지 수행합니다.)

남은 스택의 크기가 정답이 됩니다.



#include<iostream>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
#define FIO ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pii pair<int, int>
#define pll pair<long long, long long>
#define ll long long

int N;
vector <pll> vt;
pll start = make_pair(100001, 100001);

void findStart() {

 for (int i = 0; i < N; i++)
 {
  int x = vt[i].first;
  int y = vt[i].second;

  if (start.second > y) {
   start.first = x;
   start.second = y;
  }
  else if (start.second == y) {
   if (start.first > x) {
    start.first = x;
    start.second = y;
   }
  }
 }
}

ll dist(pll p1, pll p2) {
 return (p2.first - p1.first) * (p2.first - p1.first) + (p2.second - p1.second) * (p2.second - p1.second);
}

int CCW(pll p1, pll p2, pll p3) {
 ll S = (p2.first - p1.first) * (p3.second - p1.second) - (p2.second - p1.second) * (p3.first - p1.first);

 if (S > 0) return 1;
 else if (S == 0) return 0;
 else
  return -1;
}

int myCom(pll p1, pll p2) {
 int ret;
 int com = CCW(start, p1, p2);

 if (com == 0) {
  ret = (dist(start, p1) < dist(start, p2));
 }
 else if (com == 1) {
  ret = 1;
 }
 else {
  ret = 0;
 }
 return ret;
}

int main(void) {
 FIO;

 cin >> N;

 int ans = 0;

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

  vt.push_back(make_pair(x, y));
 }

 findStart();

 sort(vt.begin(), vt.end(), myCom);

 vector<pll> st;
 st.push_back(vt[0]);

 for (int i = 1; i < vt.size(); i++)
 {

  pll next = vt[i];

  while (st.size() > 1 && CCW(st[st.size() - 2], st[st.size() - 1], next) <= 0) {
   st.pop_back();
  }
  st.push_back(next);
 }

 cout << st.size();
}

댓글

이 블로그의 인기 게시물

HTML - input file 버튼 꾸미기

HTML - 이미지 미리보기(jQuery 없이)

BOJ - DNA 유사도(2612)