5개의 댓글이 있습니다.
-
-
Taeyoon_Lee -
몇년 전 로키마운틴 리저널에 나왔던 문제랑 비슷한데요, 아마 알고스팟에서도 그 문제로 모의고사를 했던 걸로 기억합니다.
유키님이 해법을 쓰셨던 걸로 기억하는데...
모든 점의 각도를 조금씩 돌려보며 수평선으로 나뉘어질 수 있는지 검사해서 풀었다고 쓰셨던 것 같아요.
16년 전 link
-
-
정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.
JongMan
Nerd or Not Nerd
Submissions: 48, accepted 3
Fast Submission: Hate Practice ^ 3 (258분)
AC Ratio: 6.25%
Writer: JongMan
이 문제는 제가 오랫동안 언젠가는 내야지 하고 별러왔던 문제입니다. 이렇게까지 낚시 문제가 될 줄은 몰랐는데 수많은 분들이 낚여서 입맛이 쓰네요 (...) 이 문제는 고전적인 문제이지만 쉽게 풀려면 풍부한 센스그리고 잘 준비된 기하 관련 prewritten 루틴들이 필요합니다. :)
기하라는 말에서 눈치채셨겠지만, 이 문제를 푸는 키포인트는 입력이 숫자 두 개라는 점을 이용해 이들을 2차원 평면에 플로팅하는 것입니다. 다음은 첫 번째 예제 입력을 2차원 평면에 플로팅한 것입니다.
앗, 감이 오시나요? 네, A * [shoe size] + B * [typing speed] = F 인 직선을 그리면, 이 직선으로 이들 집합이 정확히 구분될 수 있어야겠죠! 이와 같이, 2차원 평면에 주어진 샘플 포인트를 가르는 직선을 찾을 수 있느냐는 문제를 linear separability 라고 합니다. (인공지능이나 기계학습 분야에서는 자주 언급되는 문제죠.)
아, 물론 이 문제에서는 nerd score 가 T 이상인 사람은 무조건 nerd 고, T 미만은 일반인이라는 조건을 걸었기 때문에 문제가 달라진다고 생각할 수도 있죠. 하지만 A 와 B, F 의 부호를 모두 뒤집으면? 이 조건을 그대로 만족하게 됩니다. 따라서, 우리는 2차원 평면에서 점들을 완전히 구분할 수 있는 직선을 찾는 데 집중할 수 있습니다.
이 기하 문제의 해답은 여러 가지가 있겠지만, 저희가 의도한 방법은 볼록 껍질(Convex Hull) 을 이용하는 것입니다. 만약 두 종류의 정점을 갈라놓을 수 있는 직선이 있다면, 이들은 각 종류 정점들의 볼록 껍질 또한 구분할 수 있지요. 그리고, 두 개의 볼록 다각형은, 서로 겹치거나 닿아 있지만 않다면 이들을 구분할 방법이 반드시 존재합니다.
따라서, 볼록 껍질을 구하고 이들의 충돌 여부를 구하면 이 문제를 풀 수 있습니다. 볼록 다각형의 충돌을 검사하기 위해서는 다음과 같은 과정을 거쳐야 합니다.
1. 각 다각형의 모든 선분들에 대해, 다른 다각형의 선분과 교차하거나 닿아 있다면 충돌
2. 각 다각형의 모든 점에 대해, 다른 다각형에 포함되어 있거나 닿아 있다면 충돌
실제 대회때는 여기까지 다 온 후에도 2번 체크를 까먹으신 분들이 많은데요, 다각형의 선분이 하나도 교차하지 않더라도 하나가 다른 하나에 포함되어 있을 수도 있죠. :)
아이디어만 맞게 잡고 위에 설명한 코드만 정확하게 구현하셨으면 별다른 문제 없이 풀 수 있으셨을 거라고 생각합니다. 세 점이 한 직선 상에 있다거나, convex hull 이 면적이 없다거나 하는 예외 케이스도 있을 수 있겠지만, 데이터에서는 일부러 그런 경우를 제외하도록 했으니 튼튼한 기하 기반 라이브러리가 있다면 쉽게 해결할 수 있을 거라고 생각합니다.
아래는 레퍼런스 소스 코드입니다.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
16년 전