백준, 마인크래프트, 18111
2024. 8. 26. 18:29ㆍETC/Algorithm
[유형]
구현
[문제링크]
https://www.acmicpc.net/problem/18111
[요약]
목재를 충분히 모은 lvalue는 집을 짓기로 하였다. 하지만 고르지 않은 땅에는 집을 지을 수 없기 때문에 땅의 높이를 모두 동일하게 만드는 ‘땅 고르기’ 작업을 해야 한다.
lvalue는 세로 N, 가로 M 크기의 집터를 골랐다. 집터 맨 왼쪽 위의 좌표는 (0, 0)이다. 우리의 목적은 이 집터 내의 땅의 높이를 일정하게 바꾸는 것이다. 우리는 다음과 같은 두 종류의 작업을 할 수 있다.
- 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
- 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.
1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다. 밤에는 무서운 몬스터들이 나오기 때문에 최대한 빨리 땅 고르기 작업을 마쳐야 한다. ‘땅 고르기’ 작업에 걸리는 최소 시간과 그 경우 땅의 높이를 출력하시오.
[문제풀이]
validate_number_of_blocks: 사용가능한 블록의 개수 확인한다.
calculate_time: target_height >= height의 경우 2번째 작업을, 반대의 경우 1번째 작업을 실행한다.
시간초과가 계속 발생했는데, 예서가 예전에 풀었던 코드를 공유해줬다. validate_number_of_blocks를 실행해서 불필요한 코드 실행 횟수를 감소시켜야한다.
import sys
def input():
return sys.stdin.readline().rstrip()
# input
n, m, b = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(n)]
# init
# 최저층, 최고층
MIN, MAX = 0, 256
# 한층의 최대 갯수, 좌표 위에 있는 블록의 총 개수
CNT, SUM = n*m, 0
blocks = [0] * (MAX+1)
# 해당 층이 최고층인 블록의 개수
for i in range(n):
for j in range(m):
blocks[board[i][j]] +=1
SUM += board[i][j]
result_time = float('inf')
result_height = MAX
def validate_number_of_blocks(target_height):
return SUM + b >= target_height * CNT
def calculate_time(target_height):
time = 0
for height,count in enumerate(blocks):
if target_height >= height:
time += (target_height - height) * count
else:
time += (height - target_height) * 2 *count
return time
for h in range(MAX,MIN,-1):
if not validate_number_of_blocks(h):
continue
t = calculate_time(h)
if t < result_time:
result_time = t
result_height = h
print(result_time,result_height)
[참고] https://www.acmicpc.net/source/83003373 by 예서
'ETC > Algorithm' 카테고리의 다른 글
백준,N과 M (2),15650 (0) | 2024.08.27 |
---|---|
백준,N과 M (1),15649 (0) | 2024.08.27 |
백준,퇴사,14501 (0) | 2024.08.23 |
백준, 영화감독 숌,1436 (0) | 2024.08.23 |
백준, 중앙값 구하기, 2696 (0) | 2024.08.22 |