문제
수현이는 일년의 날짜가 1일부터 365일로 표시되어있는 달력을 가지고있다. 수현이는 너무나도 계획적인 사람이라 올 해 일정을 모두 계획해서 달력에 표시해놨다.
여름이 거의 끝나가자 장마가 시작되었고, 습기로 인해 달력에 표시한 일정이 지워지려고 한다. 지워지는 것을 막고자 수현이는 일정이 있는 곳에만 코팅지를 달력에 붙이려고 한다. 하지만 너무 귀찮았던 나머지, 다음과 같은 규칙을 따르기로 한다.
- 연속된 두 일자에 각각 일정이 1개 이상 있다면 이를 일정이 연속되었다고 표현한다.
- 연속된 모든 일정은 하나의 직사각형에 포함되어야 한다.
- 연속된 일정을 모두 감싸는 가장 작은 직사각형의 크기만큼 코팅지를 오린다.
달력은 다음과 같은 규칙을 따른다.
- 일정은 시작날짜와 종료날짜를 포함한다.
- 시작일이 가장 앞선 일정부터 차례대로 채워진다.
- 시작일이 같을 경우 일정의 기간이 긴 것이 먼저 채워진다.
- 일정은 가능한 최 상단에 배치된다.
- 일정 하나의 세로의 길이는 1이다.
- 하루의 폭은 1이다.
위의 그림에서와 같이 일정이 주어졌다고 하자. 여기서 코팅지의 면적은 아래의 파란색 영역과 같다.
이때 코팅지의 크기의 합은 3 x 8 + 2 x 2 = 28이다.
일정의 개수와 각 일정의 시작날짜, 종료날짜가 주어질 때 수현이가 자르는 코팅지의 면적을 구해보자.
입력
첫째 줄에 일정의 개수 N이 주어진다. (1 ≤ N ≤ 1000)
둘째 줄부터 일정의 개수만큼 시작 날짜 S와 종료 날짜 E가 주어진다. (1 ≤ S ≤ E ≤ 365)
출력
코팅지의 면적을 출력한다.
풀이 과정
코팅지를 붙이는 면적을 계산하는 과정은 연속된 일정들의 날짜 x 가장 많이 일정이 쌓인 날의 일정 개수 로 쉽게 구할 수 있으나, 일정들을 쌓는 과정에서 생각이 필요한 문제이다.
먼저 일정들을 시작일이 빠른 순서대로, 시작일이 같다면 일정 기간이 긴 순서대로 정렬한 뒤, 일정이 겹치지 않는 선에서 해당 날짜의 첫 번째 일정부터 차곡차곡 쌓는 과정을 구현한다.
그림으로 표현한다면 다음과 같다.
시작일이 빠른 순서대로, 시작일이 같다면 일정이 긴 순서대로 정렬된 일정들 중 첫 번째 일정들을 각각 배치했을 때, 다른 일정들과 겹치는 일정들은 두 번째 일정으로 배치할 수 있도록 남겨놓는다. ( 즉, 겹치지 않게 일정들을 먼저 쭉 배치하고 그 후에 남은 일정들을 계속해서 배치하는 아이디어이다. )
다음과 같이 구현하여 필요한 코팅지의 면적을 구할 수 있다.
import sys
input = sys.stdin.readline
n = int(input().rstrip())
times = [0 for _ in range(366)]
arr = [list(map(int, input().rstrip().split())) for _ in range(n)]
arr.sort(key=lambda x:(x[0], -(x[1] - x[0])))
for i in range(1, 1001):
arr_size = len(arr)
if arr_size == 0: break
lastarr = []
for j in range(arr_size):
mt = max(times[arr[j][0]:arr[j][1]+1])
if mt != i:
for ki in range(arr[j][0], arr[j][1]+1):
times[ki] = mt + 1
else: lastarr.append(arr[j])
arr = []
for l in lastarr: arr.append(l)
max_height = 0
start_day = 1
result = 0
for i in range(1, 366):
if times[i] == 0:
result += max_height * (i - start_day)
max_height = 0
start_day = i+1
else:
max_height = max(max_height, times[i])
if max_height != 0:
result += max_height * (366 - start_day)
print(result)
'-- 예전 기록 > BOJ' 카테고리의 다른 글
[ BOJ ] 10997 : 별 찍기 - 22 ( SILVER 2 ) / Python (0) | 2024.01.29 |
---|---|
[ BOJ ] 17087 : 숨바꼭질 6 ( SILVER 2 ) / Python (0) | 2024.01.29 |
[ BOJ ] 13023 : ABCDE ( GOLD 5 ) / Python (0) | 2024.01.29 |
[ BOJ ] 15927 : 회문은 회문아니야!! ( GOLD 5 ) / Python (0) | 2024.01.29 |
[ BOJ ] 21610 : 마법사 상어와 비바라기 ( GOLD 5 ) / Python (0) | 2024.01.28 |