문제
https://www.acmicpc.net/problem/18111
걸린 시간
02 : 49 : 28 실패
시간 초과 풀이
Python3
if __name__ == "__main__":
# 집터의 세로 : N, 가로 : M, 인벤토리의 블록 : B
N, M, B = map(int, input().split())
house = []
for i in range(0, N):
tmp = list(map(int, input().split()))
for j in tmp:
house.append(j)
maximum = max(house)
minimum = min(house)
candidateBlock = []
for standard in range(minimum, maximum + 1):
distroyBlock = 0
needBlock = 0
time = 0
for land in house:
# 땅이 기준으로 정한 값 보다
# 높을 때 (제거)
block = land - standard
if land > standard:
distroyBlock += block
time += block * 2
# 낮을 때 (추가)
elif land < standard:
needBlock += abs(block)
time += abs(block) * 1
else:
pass
# 가지고 있는 블럭의 개수가 필요한 땅의 개수보다 많을 때
if needBlock <= B + distroyBlock:
# 걸린 시간과 높이를 리스트로 묶어 저장
candidateBlock.append([time, standard])
# 시간 최소값을 가져옴
bestTime = min(candidateBlock)[0]
# 정답이 여러개일 경우 가장 큰 높이를 가져옴
for i in candidateBlock:
if i[0] == bestTime:
bestStandard = i[1]
print(bestTime, bestStandard)
가능한 경우의 수를 일일이 모두 탐색해보는 완전 탐색;브루트 포스(Brute-force) 문제이다.
최악의 경우 최소 반복 횟수가 257 * 500 * 500 = 64,250,250
번 이상이기 때문이다. Python3 으로는 통과할 수 없다.
옳은 풀이
Python3
if __name__ == "__main__":
# 집터의 세로 : N, 가로 : M, 인벤토리의 블록 : B
N, M, B = map(int, input().split())
# 땅의 높이 : height
height = [0] * 257
for i in range(0, N):
tmp = list(map(int, input().split()))
for j in tmp:
height[j] += 1
# 높이 후보 : candidateBlock
candidateBlock = []
for standard in range(0, 257):
distroyBlock = 0
needBlock = 0
time = 0
for land in range(0, 257):
# 땅이 기준으로 정한 값 보다
# 높을 때 (제거)
block = land - standard
if land > standard:
distroyBlock += block * height[land]
time += block * 2 * height[land]
# 낮을 때 (추가)
elif land < standard:
needBlock += abs(block) * height[land]
time += abs(block) * 1 * height[land]
else:
pass
# 가지고 있는 블럭의 개수가 필요한 땅의 개수보다 많을 때
if needBlock <= B + distroyBlock:
# 걸린 시간과 높이를 리스트로 묶어 저장
candidateBlock.append([time, standard])
# 시간 최소값을 가져옴
bestTime = min(candidateBlock)[0]
# 정답이 여러개일 경우 가장 큰 높이를 가져옴
for i in candidateBlock:
if i[0] == bestTime:
bestStandard = i[1]
print(bestTime, bestStandard)
높이가 0부터 256사이의 작은 범위의 값임을 이용해 중복되는 값을 배열의 인덱스를 사용하여 묶어주면 257 * 257 = 66,049
로 반복 횟수가 크게 줄어들게 된다.
앞으로 시간초과가 날 땐 가장 큰 테스트 케이스를 적용시켜보고 어느 부분이 문제인지 찾는 습관을 들여야겠다.
참고
'Baekjoon' 카테고리의 다른 글
Baekjoon 10848번 큐 (0) | 2020.07.19 |
---|---|
Baekjoon 10828번 스택 (0) | 2020.07.18 |
Baekjoon 2805번 나무 자르기 (0) | 2020.07.17 |
Baekjoon 1654번 랜선 자르기 (0) | 2020.07.16 |
Baekjoon 4153번 직각삼각형 (0) | 2020.07.16 |
댓글