[알고리즘]백준 2477번: 참외밭
알고리즘 유형: 수학(기하학)
문제
시골에 있는 태양이의 삼촌 댁에는 커다란 참외밭이 있다. 문득 태양이는 이 밭에서 자라는 참외가 도대체 몇 개나 되는지 궁금해졌다. 어떻게 알아낼 수 있는지 골똘히 생각하다가 드디어 좋은 아이디어가 떠올랐다. 유레카! 1m2의 넓이에 자라는 참외 개수를 헤아린 다음, 참외밭의 넓이를 구하면 비례식을 이용하여 참외의 총개수를 구할 수 있다.
1m2의 넓이에 자라는 참외의 개수는 헤아렸고, 이제 참외밭의 넓이만 구하면 된다. 참외밭은 ㄱ-자 모양이거나 ㄱ-자를 90도, 180도, 270도 회전한 모양(┏, ┗, ┛ 모양)의 육각형이다. 다행히도 밭의 경계(육각형의 변)는 모두 동서 방향이거나 남북 방향이었다. 밭의 한 모퉁이에서 출발하여 밭의 둘레를 돌면서 밭경계 길이를 모두 측정하였다.

예를 들어 참외밭이 위 그림과 같은 모양이라고 하자. 그림에서 오른쪽은 동쪽, 왼쪽은 서쪽, 아래쪽은 남쪽, 위쪽은 북쪽이다. 이 그림의 왼쪽위 꼭짓점에서 출발하여, 반시계방향으로 남쪽으로 30m, 동쪽으로 60m, 남쪽으로 20m, 동쪽으로 100m, 북쪽으로 50m, 서쪽으로 160m 이동하면 다시 출발점으로 되돌아가게 된다.
위 그림의 참외밭 면적은 6800m2이다. 만약 1m2의 넓이에 자라는 참외의 개수가 7이라면, 이 밭에서 자라는 참외의 개수는 47600으로 계산된다.
1m2의 넓이에 자라는 참외의 개수와, 참외밭을 이루는 육각형의 임의의 한 꼭짓점에서 출발하여 반시계방향으로 둘레를 돌면서 지나는 변의 방향과 길이가 순서대로 주어진다. 이 참외밭에서 자라는 참외의 수를 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 1m2의 넓이에 자라는 참외의 개수를 나타내는 양의 정수 K (1 ≤ K ≤ 20)가 주어진다. 참외밭을 나타내는 육각형의 임의의 한 꼭짓점에서 출발하여 반시계방향으로 둘레를 돌면서 지나는 변의 방향과 길이 (1 이상 500 이하의 정수) 가 둘째 줄부터 일곱 번째 줄까지 한 줄에 하나씩 순서대로 주어진다. 변의 방향에서 동쪽은 1, 서쪽은 2, 남쪽은 3, 북쪽은 4로 나타낸다.
출력
첫째 줄에 입력으로 주어진 밭에서 자라는 참외의 수를 출력한다.
풀이

도형은 변의 길이나 방향이 조금 다를 수 있어도, 형태는 위와 같이 생겼습니다.
넓이는 단순하게 구할 수 있습니다 아래의 그림처럼 큰 사각형에서 작은 사각형(빨간색)의 넓이를 빼주면 됩니다

문제에서는 입력으로 방향과 거리를 받습니다.
동시에 각 좌표를 저장해주는 배열을 하나 만들어주겠습니다. 초기 위치는 0,0으로 잡고 가겠습니다
이렇게 움직이다보면, 빨간색 사각형의 꼭지점에 해당하는 부분 하나는 방문 하지 않으므로 배열에 저장되지 않습니다

이 좌표가 뭔지 확인하기 위해서 다음 네 좌표가 배열에 있는지 없는지 확인해보면 됩니다
이를 통해서 방문하지 않았지만, 작은 사각형의 넓이를 구하기 위해 필요한 좌표, empty를 조건문을 통해 찾아줍니다
마지막으로 사각형 넓이 공식을 활용해 넓이를 계산해주고 참외밭의 1m^2당 생산량을 곱해주면 끝납니다
코드가 굉장히 비효율적으로 보이지만(실제로 비효율적입니다)
배열의 크기가 매우 작기 때문에 단순한 방식으로 풀이가 가능합니다
import sys
N = int(sys.stdin.readline().strip())
point = [[0,0]]
def update(direction, diff, point):
if direction ==1:
point.append([point[-1][0]+diff, point[-1][1]])
if direction ==2:
point.append([point[-1][0]-diff, point[-1][1]])
if direction ==3:
point.append([point[-1][0], point[-1][1]-diff])
if direction ==4:
point.append([point[-1][0], point[-1][1]+diff])
return point
for i in range(6):
direction, diff = map(int, sys.stdin.readline().strip().split(" "))
point = update(direction, diff, point)
x= sorted([ x[0] for x in point])
y = sorted([ y[1] for y in point])
min_x, max_x, min_y, max_y = min(x), max(x), min(y), max(y)
mid_x, mid_y = x[3], y[3]
if [max_x, max_y] not in point:
empty = [max_x, max_y]
if [max_x, min_y] not in point:
empty = [max_x, min_y]
if [min_x, max_y] not in point:
empty = [min_x, max_y]
if [min_x, min_y] not in point:
empty = [min_x, min_y]
A = (max_x - min_x)*(max_y-min_y)-abs(mid_x-empty[0])*abs(mid_y-empty[1])
print(A*N)