참외밭
1 초 | 128 MB | 6620 | 2483 | 2086 | 38.983% |
문제
시골에 있는 태양이의 삼촌 댁에는 커다란 참외밭이 있다. 문득 태양이는 이 밭에서 자라는 참외가 도대체 몇 개나 되는지 궁금해졌다. 어떻게 알아낼 수 있는지 골똘히 생각하다가 드디어 좋은 아이디어가 떠올랐다. 유레카! 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로 나타낸다.
출력
첫째 줄에 입력으로 주어진 밭에서 자라는 참외의 수를 출력한다.
풀이1
추상화가 필요해보였습니다. 임의의 배열, 리스트 안에 방향은 존재하지 않으므로 수학적인 접근이 필요했습니다.
가로, 세로 분리 = 최대사각형
가로는 [1, 2] 세로는 [3, 4]로 나누어집니다.
가로 중의 최대 길이와 세로길의 최대길이를 구하면 일단 최대 사각형을 구할 수 있습니다.
작은 사각형
모양의 규칙성에 주목하면 최대 길이 바로 옆에 붙어있는 선분들은 최소사각형을 구성하지 않습니다.
정리하면?
위에 표시한 O를 기준(최대값들 사이)으로 사슬처럼 연결되어있습니다.
붙어있는 변 - 최대 가로 - 최대 세로 - 붙어있는 변
예외 발생 가능성
그러나 인덱스에 그냥 값을 집어넣으면 인덱스 끝에 있는 경우 다음처럼 연결이 안된 것처럼 보일 수 있습니다
[ 최대 세로 - 붙어 있는 변 - 최소 변 - 최소변 - 붙어 있는 변 - 최대 가로]
위 사슬 모양을 제외하고 양쪽 변만 더해주면 되므로 이것을 두 번 이어붙이고 최소변을 찾아줍니다.
[ 최대 세로 - 붙 변 - 최소 변 - 최소변 - 붙 변 - 최대 가로] [ 최대 세로 - 붙 변 - 최소 변 - 최소변 - 붙 변 - 최대 가로]
위 처럼 연결했을 때 붙어있는 변을 빠르게 찾아낼 수 있습니다.
하지만 위의 방식을 응용해 더 간단하게 풀어보고 싶었습니다.
풀이2
가장 큰 선분들을 제외한 나머지 선분들로 넓이를 구하는 것입니다.
굴곡이 생기는 부분에서 방향은 → ↑ → ↑ 처럼 반복합니다.
그럼 이 구간을 찾으면 →→ 와 ↑↑ 는 각각 최대변이 되고 ↑ → 는 최소변이 됨을 알 수 있습니다.
6개의 값 중에 2값 빼고는 반복되는 값이므로 찾기 위해 리스트를 이어 붙입니다.
[ 변 - 최대변- 최대변 - 변 - 변 - 변] [ 변 - 최대변- 최대변 - 변 - 변 - 변]
그래서 위처럼 겹치는 부분을 찾으면 가져와서 작은 사각형과 큰 사각형을 구해 넓이를 구합니다.
N = int(input())
land = []
for i in range(6):
land.append(list(map(int, input().split())))
land.extend(land) #이어 붙이기
for i in range(9): # 반복되는 숫자 검사
if land[i][0] == land[i+2][0] and land[i+1][0] == land[i+3][0]:
# i i+1 i+2 i+3
print(N*((land[i][1]+land[i+2][1])*(land[i+1][1]+land[i+3][1])-land[i+1][1]*land[i+2][1]))
break
'Study > Baekjoon' 카테고리의 다른 글
[Python] Baekjoon1929: 소수 구하기 (0) | 2022.01.31 |
---|---|
[Python] Baekjoon2527: 직사각형 (0) | 2022.01.30 |
[Python] Baekjoon2578: 빙고, 오답이 될 수 있는 경우는? (0) | 2022.01.29 |
[Python] Baekjoon2559: 수열 (0) | 2022.01.29 |
[Python] Baekjoon2304: 창고 다각형 (0) | 2022.01.29 |