728x90
문제 링크: https://www.acmicpc.net/problem/2254
2254번: 감옥 건설
첫째 줄에 N(1≤N≤1,000), Px, Py (-100,000≤Px, Py≤100,000)이 주어진다. 다음 N개의 줄에는 차례로 담 기둥의 좌표가 주어진다. 각각의 좌표는 절댓값이 100,000을 넘지 않는 정수이다.
www.acmicpc.net
문제 풀이
볼록 껍질 문제이다. 모노톤 체인 기법으로 풀었으며, 다각형 내부의 점 판정은 CCW로 간단하게 구할 수 있다.
볼록 껍질에 대한 자세한 내용은 나중에 직접 다룰 예정이다.
볼록 껍질을 만들 수 있을 때까지 반복문을 돌려주고, 먼저 가장 먼 외각의 볼록 껍질이 완성된다. Px, Py의 좌표(점을
만약 볼록 껍질이 만들어지고 내부의 점이라면 개수에 +1을 해주자. 또한 모든 점에서 볼록 껍질이 만들어진 점을 빼려고 set을 이용하여 차집합하여 빼줬다.
코드
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
input = sys.stdin.readline | |
def ccw(t1, t2, t3): | |
x1, y1 = t1 | |
x2, y2 = t2 | |
x3, y3 = t3 | |
s = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1) | |
if s > 0: | |
return True | |
else: | |
return False | |
n, px, py = map(int, input().split()) | |
pxy = (px, py) | |
dots = [] | |
for _ in range(n): | |
dots.append(tuple(map(int, input().split()))) | |
convex_hull_possible = True | |
count = 0 | |
while convex_hull_possible and len(dots) > 2: #컨백스 헐 만들수 있을 때 까지 수행 | |
dots.sort() # 좌표 정렬 | |
bch, tch = [], [] #25줄부터 58줄까지 컨백스 헐 만들기(모노톤 체인) | |
bch.append(dots[0]) | |
bch.append(dots[1]) | |
for i in range(2, n): | |
bch.append(dots[i]) | |
p = True | |
while p and len(bch) > 2: | |
d1 = bch.pop() | |
d2 = bch.pop() | |
if ccw(bch[-1], d2, d1): | |
bch.append(d2) | |
bch.append(d1) | |
p = False | |
else: | |
bch.append(d1) | |
tch.append(dots[-1]) | |
tch.append(dots[-2]) | |
for i in range(n-3, -1, -1): | |
tch.append(dots[i]) | |
p = True | |
while p and len(tch) > 2: | |
d1 = tch.pop() | |
d2 = tch.pop() | |
if ccw(tch[-1], d2, d1): | |
tch.append(d2) | |
tch.append(d1) | |
p = False | |
else: | |
tch.append(d1) | |
bch.pop() | |
convex_hull = bch+tch | |
dots = list(set(dots) - set(convex_hull)) | |
n = len(dots) | |
for i in range(len(convex_hull)-1): # 점 3개를 이용하여(px, py를 포함) px, py가 밖의 점인지 안의 점인지 확인 | |
if not ccw(convex_hull[i], convex_hull[i+1], pxy): | |
convex_hull_possible = False | |
break | |
if convex_hull_possible: # 안에 있는 점이라면 개수 추가 아니면 반복문까지 종료 | |
count += 1 | |
print(count) |
728x90
'BOJ' 카테고리의 다른 글
[BOJ][Python] 백준 1547번 - 공 (0) | 2021.09.22 |
---|---|
[BOJ][Python] 백준 2101번 - 플러그 (0) | 2021.09.22 |
[BOJ][Python] 백준 18870번 - 좌표 압축 (0) | 2021.09.22 |
[BOJ][Python] 백준 14621번 - 나만 안되는 연애 (0) | 2021.09.21 |
[BOJ][Python] 백준 2903번 - 중앙 이동 알고리즘 (0) | 2021.09.21 |