일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 파이썬 자료형
- 컴퓨터 동작방식
- icmp
- 데이터 통신과 컴퓨터 네트워크
- 파이썬 연산자
- 기억장치
- 이것이 취업을 위한 코딩테스트다
- OSI7계층모델
- GIT
- 쿠키
- sort()
- 데이터통신
- DP
- 컴퓨터네트워크
- 라우팅
- 이것이 취업을 위한 코딩 테스트다
- 시스템 소프트웨어
- ARP
- 리스트
- CS
- 자료형
- 파이썬 정렬
- 북클럽
- 노개북
- data type
- 노마드코더
- RARP
- 이코테
- IT5분잡학사전
- 쉽게 배우는 데이터 통신과 컴퓨터 네트워크
- Today
- Total
뚝딱햄 탈출기
[Python][백준 BOJ Silver V] 2628. 종이 자르기 : 정렬, 리스트 컴프리헨션을 활용한 출력 본문
[Python][백준 BOJ Silver V] 2628. 종이 자르기 : 정렬, 리스트 컴프리헨션을 활용한 출력
hyrmzz1 2023. 12. 16. 14:35
접근 방식
접근을 어떻게 해야 할지 아이디어를 떠올리는데 꽤나 걸렸다. 핵심은 정렬!!
- 가장 큰 종이 조각의 넓이를 출력하려면, 어떤 식으로 잘린 상태인지 알아야 한다.
- 가로 세로 각각 가장 긴 길이를 가진 사각형이 가장 큰 넓이를 가진 사각형!
- 따라서 사각형이 가질 수 있는 가로와 세로 길이를 알아야 한다.
- 우선 가로, 세로 잘린 점들을 넣을 배열을 각각 선언하고
- 가로 세로 입력값과, 원래 직사각형의 가로 세로 원점과 끝점을 선언한 배열에 각각 넣는다.
- 그 후 정렬을 하면
- 각 배열에서 element와 다음(또는 이전) element의 차를 이용해 길이를 구할 수 있다.
- 가장 큰 가로/세로 길이를 곱해 출력한다.
잘린 사각형들의 가로/세로 길이를 구하기 위해서는 정렬을 해야 한다. ⭐
세로 배열에는 입력값인 3, 2와 본래 직사각형의 세로 길이인 8, 원점인 0이 들어있다. (처음엔 [0, 8, 3, 2] 상태)
직사각형들의 세로 길이인 2, 1, 5(그림 참고)를 구하려면 배열이 정렬된 상태([0, 2, 3, 8])에서 나란히 있는 element들의 차를 이용하면 편하다.
구현할 때 출력 부분이 내가 느끼기엔 까다로워서 어떻게 깔끔하게 작성할 수 있을지에 대한 고민이 많았는데,
리스트 컴프리헨션을 출력할 때도 사용할 수 있다는 걸 알게 되었다.
✅ Solution 1 - 출력 시 리스트 컴프리헨션 사용
import sys
w, h = map(int, sys.stdin.readline().split())
width = [0, w] # 원점, 끝점
height = [0, h] # 원점, 끝점
n = int(sys.stdin.readline()) # 점선 개수
for _ in range(n):
a, b = map(int, sys.stdin.readline().split())
if a == 0:
height.append(b)
else:
width.append(b)
height.sort()
width.sort()
print(
max([width[i] - width[i - 1] for i in range(1, len(width))])
*
max([height[i] - height[i - 1] for i in range(1, len(height))])
)
원래는 아래처럼 작성하려고 했다.
w_list = [width[i] - width[i - 1] for i in range(1, len(width))]
h_list = [height[i] - height[i - 1] for i in range(1, len(height))]
print(max(w_list) * max(h_list))
그러나 print()문 내에서도 리스트 컴프리헨션을 이용할 수 있다는 걸 알게되었다. 변수명 작성 안해도 되서 맘에 든다 ㅎ
✅ Solution 2 - 리스트 컴프리헨션 사용 X
import sys
w, h = map(int, sys.stdin.readline().split())
width = [0, w] # 원점, 끝점
height = [0, h] # 원점, 끝점
n = int(sys.stdin.readline()) # 점선 개수
for _ in range(n):
a, b = map(int, sys.stdin.readline().split())
if a == 0:
height.append(b)
else:
width.append(b)
height.sort()
width.sort()
h_list = []
w_list = []
for i in range(1, len(height)):
x = height[i] - height[i-1]
h_list.append(x)
for j in range(1, len(width)):
y = width[j] - width[j-1]
w_list.append(y)
print(max(h_list)*max(w_list))
리스트 컴프리헨션은 리스트 초기화부터 원소 삽입까지 한번에 할 수 있다.
리스트 컴프리헨션을 사용하지 않고 Solution 1의 로직으로 구현하려면 우선 두개의 리스트를 초기화하고(h_list
, w_list
) for문을 돌면서 원소를 하나씩 삽입해준다. 이후 각 리스트의 최댓값끼리 곱하면 가장 큰 넓이를 구할 수 있다.
리스트 컴프리헨션을 사용하지 않으니 코드가 좀 더 지저분하게 느껴진다.
✳️ Solution 3 - 새롭게 알게된 방식 (이중 for문 내에서 최댓값 찾기)
import sys
w, h = map(int, sys.stdin.readline().split())
width = [0, w] # 원점, 끝점
height = [0, h] # 원점, 끝점
n = int(sys.stdin.readline()) # 점선 개수
for _ in range(n):
a, b = map(int, sys.stdin.readline().split())
if a == 0:
height.append(b)
else:
width.append(b)
height.sort()
width.sort()
max_area = 0
for i in range(1, len(height)):
for j in range(1, len(width)):
x = height[i] - height[i-1]
y = width[j] - width[j-1]
max_area = max(x*y, max_area)
print(max_area)
다른 방식을 알게되어 코드를 작성해보았다.
이중 for문으로 넓이의 모든 경우의 수를 구하고, max()
를 이용해 max_area
의 기존 값과 비교해 해당 루프에서의 x*y
가 더 크다면 max_area
의 값을 바꾸어준다.
즉, for문이 도는 동안 max_area
의 값은 계속해서 최대값으로 갱신될 것이다.
💭 What I Learned
- 이런 유형의 문제를 풀 때 정렬을 사용한다.
- 출력할 때도 리스트 컴프리헨션을 활용할 수 있다.
https://www.acmicpc.net/problem/2628