일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Java
- C언어
- 최단 경로
- 백준
- 배열
- SWEA
- php 프로그래밍 입문
- php
- php 프로그래밍
- 자바
- php 프로그래밍 입문 솔루션
- 페이코 추천인코드
- spring
- 페이코 추천인
- 자바 스프링
- 파이썬
- 스프링
- 한정 분기
- php 프로그래밍 입문 문제풀이
- Flutter
- php 프로그래밍 입문 3판
- programmers
- php 프로그래밍 입문 예제
- 플러터
- 페이코 친구코드
- 페이코 초대코드
- php 프로그래밍 입문 연습문제
- 플러터 개발환경 설정
- C
- JAVA SPRING
- Today
- Total
ImJay
[파이썬/Python] 백준 18111번 마인크래프트 본문
[파이썬/Python] 백준 18111번 마인크래프트
문제
팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게 땅을 파거나 집을 지을 수 있는 게임이다.
목재를 충분히 모은 lvalue는 집을 짓기로 하였다. 하지만 고르지 않은 땅에는 집을 지을 수 없기 때문에 땅의 높이를 모두 동일하게 만드는 ‘땅 고르기’ 작업을 해야 한다.
lvalue는 세로 N, 가로 M 크기의 집터를 골랐다. 집터 맨 왼쪽 위의 좌표는 (0, 0)이다. 우리의 목적은 이 집터 내의 땅의 높이를 일정하게 바꾸는 것이다. 우리는 다음과 같은 두 종류의 작업을 할 수 있다.
- 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
- 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.
1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다. 밤에는 무서운 몬스터들이 나오기 때문에 최대한 빨리 땅 고르기 작업을 마쳐야 한다. ‘땅 고르기’ 작업에 걸리는 최소 시간과 그 경우 땅의 높이를 출력하시오.
단, 집터 아래에 동굴 등 빈 공간은 존재하지 않으며, 집터 바깥에서 블록을 가져올 수 없다. 또한, 작업을 시작할 때 인벤토리에는 B개의 블록이 들어 있다. 땅의 높이는 256블록을 초과할 수 없으며, 음수가 될 수 없다.
입력
첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 107)
둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다. (i + 2)번째 줄의 (j + 1)번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다. 땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.
출력
첫째 줄에 땅을 고르는 데 걸리는 시간과 땅의 높이를 출력하시오. 답이 여러 개 있다면 그중에서 땅의 높이가 가장 높은 것을 출력하시오.
예제 입력
3 4 99
0 0 0 0
0 0 0 0
0 0 0 1
예제 출력
2 0
맨 오른쪽 아래의 블록을 제거하면 모두 높이가 0으로 고른 상태가 된다. 따라서 블럭을 한 번 제거하는 시간 2초가 소요된다.
풀이 1
PyPy3
import sys
input = sys.stdin.readline
# 입력
n, m, b = map(int, input().split())
lst = [list(map(int, input().split())) for _ in range(n)]
# 시간, 높이 설정
mintime = sys.maxsize
maxheight = 0
# 최대 높이는 256이므로, 0~256 까지 탐색
for h in range(257):
tmp = b
time = 0
for r in lst:
for c in r:
# 현재 좌표의 높이가 목표 높이보다 낮을 때,
# 블록을 제거하고 인벤토리에 넣어야 한다.
if c < h:
tmp -= (h-c)
time += 1 * (h-c)
# 현재 좌표의 높이가 목표 높이보다 높을 때,
# 인벤토리에서 블록을 꺼내어 쌓아야 한다.
elif c > h:
tmp += (c-h)
time += 2 * (c-h)
# 인벤토리에 남은 블록 수가 0 이상이고,
# 현재까지의 시간이 최소 시간보다 작거나 같을 때,
# 최소 시간과 최대 높이를 갱신한다.
if tmp >= 0 and mintime >= time:
mintime = time
maxheight = h
print(mintime, maxheight)
이 코드의 시간 복잡도는 O(NM)이다.
코드의 주요 반복문은 h를 0부터 256까지 순회하는 반복문과 이중 반복문으로 구성되어 있다. 이중 반복문은 집터의 각 좌표를 모두 순회하므로 O(NM)의 시간이 걸린다. 따라서 전체 코드의 시간 복잡도는 O(NM)이 됩니다.
여기서 N은 집터의 세로 길이, M은 집터의 가로 길이를 나타낸다.
풀이 2
Python 3
import sys
input=sys.stdin.readline
def sol():
n, m, b = map(int, input().split())
data = [0] * 257
# 각 높이별로 등장하는 땅의 개수를 세는 작업
for _ in range(n):
for i in map(int, input().split()):
data[i] += 1
have = sum(i * data[i] for i in range(257)) # 현재 인벤토리에 가지고 있는 블록 수
ans = (have * 2, 0) # 초기 값으로 최대 시간과 땅의 높이를 설정
need = 0
t = data[0] # 높이 0의 땅의 개수
nm = n * m # 집터의 총 땅의 개수
# 높이를 1부터 256까지 순회하며 최소 시간과 땅의 높이를 갱신하는 작업
for i in range(1, 257):
need += t
have -= nm - t
t += data[i]
if have + b - need < 0:
# 인벤토리에 남은 블록 수가 필요한 블록 수보다 작아지면 종료
break
else:
ans = min((have * 2 + need, -i), ans) # 최소 시간과 최대 높이를 갱신
print(ans[0], -ans[1])
sol()
data 리스트를 구성하는 이중 반복문은 O(NM)의 시간이 걸린다.
높이를 1부터 256까지 순회하는 반복문은 상수 시간이 소요되므로 O(1)이다.
따라서 전체 코드의 시간 복잡도는 O(NM)이다.
참고자료
'Solved.ac - Python > CLASS 2' 카테고리의 다른 글
[파이썬/Python] 백준 11651번 좌표 정렬하기 2 (0) | 2023.05.24 |
---|---|
[파이썬/Python] 백준 15829번 Hashing (0) | 2023.05.24 |
[파이썬/Python] 백준 10989번 수 정렬하기 3 (0) | 2023.05.21 |
[파이썬/Python] 백준 10773번 제로 (0) | 2023.05.20 |
[파이썬/Python] 백준 7568번 등치 (3) | 2023.05.20 |