R
: 행의 수 ()
C
: 열의 수 ()
K
: 검사 온도 ()
W
: 벽의 개수 ()
많이 어려워서 참고하면서 풀었다.
크기가 R×C인 집의 온도를 실시간으로 모니터링하면서 초콜릿을 먹을 때, 총 몇 개를 먹는지 구하는 문제이다.
성능 테스트 작업 순서
⭐️ 온도 증가 방식
- 온풍기에서 바람 나옴
- 바람 나오는 방향 4가지 중 1개
- 위, 아래, 왼쪽, 오른쪽
- 바람 나오는 방향에 따라 온도 증가
- ⚠️ 바람 1번 나왔을 때 온도 증가
- 바람 나오는 칸 = 항상 온도 5도
- 다른 칸으로 이동
- (x, y)에 바람 도달해 온도
k
라면?
- (x-1, y+1), (x, y+1), (x+1, y+1)의 온도 =
k-1
- 어떤 칸에 같은 온풍기의 바람 여러 번 도착해도 온도 여러번 상승 ❌
- 벽이 있는 칸은 온풍기 바람 통과 ❌
- 온풍기 여러 개 → 상승한 온도 모두 합한 값이 해당 칸의 상승한 온도
⭐️ 온도 조절 방식
- 모든 인접한 칸에 대해 조절
- 벽이 있으면 온도 조절 ❌
- 모든 칸에 대해 동시에 발생하는 과정
- 온도 높은 칸 → 낮은 칸으로 만큼 조절
- 온도 높은 칸 : 이 값만큼 🔻
- 온도 낮은 칸 : 이 값만큼 🔺
→ 각 과정이 매우 복잡하므로 여러 개의 함수로 나눠서 구현하면 좋을 것 같다.
입력받을 변수들을 정리한다.
이용할 변수들을 정의해준다.
t = 0
이면 (x, y)와 (x-1, y) 사이 벽 ⭕️t = 1
이면 (x, y)와 (x, y+1) 사이 벽 ⭕️온풍기 바람이 1번 나올 때마다 동작해야 하는 일들을 함수로 구현해준다.
온도 증가 함수
온도 조절 함수
바깥쪽 칸 온도 감소 함수
성능 테스트
체스판 입력 →
턴 수 1000번까지 K개의 말 이동하며 함수 수행 →
최종 시간복잡도
로,최악의 경우 이 되어 제한 시간 0.5초 내에 연산이 가능하다.
import sys
from collections import deque
input = sys.stdin.readline
# 4가지 이동 방향 정의 (0 : 오른쪽, 1 : 왼쪽, 2 : 위, 3 : 아래)
moves = [(0, 1), (0, -1), (-1, 0), (1, 0)]
# 온도 증가 함수
def temp_up(r, c, dir):
visited = [[False] * C for _ in range(R)]
queue = deque([(r + moves[dir][0], c + moves[dir][1], 5)])
while queue:
r, c, temp = queue.popleft()
room[r][c] += temp
if temp > 1: # 온도가 1보다 클 경우, 인접 칸에 온도 전달
nr, nc = r + moves[dir][0], c + moves[dir][1]
if 0 <= nr < R and 0 <= nc < C:
if not wall[dir][r][c] and not visited[nr][nc]:
queue.append((nr, nc, temp - 1))
visited[nr][nc] = True
if dir >= 2: # 위/아래 방향 추가 탐색
if c - 1 >= 0 and not wall[1][r][c] and not wall[dir][r][c - 1] and not visited[nr][c - 1]:
queue.append((nr, c - 1, temp - 1))
visited[nr][c - 1] = True
if c + 1 < C and not wall[0][r][c] and not wall[dir][r][c + 1] and not visited[nr][c + 1]:
queue.append((nr, c + 1, temp - 1))
visited[nr][c + 1] = True
else: # 좌/우 방향 추가 탐색
if r - 1 >= 0 and not wall[2][r][c] and not wall[dir][r - 1][c] and not visited[r - 1][nc]:
queue.append((r - 1, nc, temp - 1))
visited[r - 1][nc] = True
if r + 1 < R and not wall[3][r][c] and not wall[dir][r + 1][c] and not visited[r + 1][nc]:
queue.append((r + 1, nc, temp - 1))
visited[r + 1][nc] = True
# 온도 조절 함수
def control_temp():
new_room = [[room[r][c] for c in range(C)] for r in range(R)]
for r in range(R):
for c in range(C):
for k in [0, 3]: # 오른쪽과 아래 방향
nr, nc = r + moves[k][0], c + moves[k][1]
if 0 <= nr < R and 0 <= nc < C and not wall[k][r][c]:
# 온도 차이 계산
diff = abs(room[r][c] - room[nr][nc]) // 4
# 온도 조절
if room[r][c] > room[nr][nc]:
new_room[r][c] -= diff
new_room[nr][nc] += diff
else:
new_room[r][c] += diff
new_room[nr][nc] -= diff
return new_room
# 바깥쪽 칸 온도 감소 함수
def temp_down():
for i in range(C):
if room[0][i] > 0:
room[0][i] -= 1
if room[R - 1][i] > 0:
room[R - 1][i] -= 1
for i in range(1, R - 1):
if room[i][0] > 0:
room[i][0] -= 1
if room[i][C - 1] > 0:
room[i][C - 1] -= 1
# R, C, K 입력
R, C, K = map(int, input().split())
# 방 정보 입력
room = []
heater = [] # 온풍기 위치
check_temp = [] # 온도 조사 위치
for i in range(R):
row = list(map(int, input().split()))
for j in range(C):
if row[j] == 5:
check_temp.append((i, j)) # 온도 조사할 구간 추가
elif row[j] > 0:
heater.append((i, j, row[j])) # 온풍기 위치 추가
room.append([0] * C) # 온도 저장에 이용
# 벽의 개수 입력
W = int(input())
# 벽 정보 입력
wall = [[[False] * C for _ in range(R)] for _ in range(4)]
for _ in range(W):
x, y, t = map(int, input().split())
x -= 1
y -= 1
if t == 0: # 위/아래 벽
wall[2][x][y] = True
wall[3][x - 1][y] = True
else: # 왼쪽/오른쪽 벽
wall[0][x][y] = True
wall[1][x][y + 1] = True
# 초콜릿 개수 저장 변수 정의
choco = 0
# 성능 테스트 시작
while True:
# 1. 온풍기 작동
for r, c, dir in heater:
temp_up(r, c, dir - 1)
# 2. 온도 조절
room = control_temp()
# 3. 바깥쪽 칸 온도 감소
temp_down()
# 4. 초콜릿 추가
choco += 1
# 5. 온도 조사 위치 확인
all_good = True
for r, c in check_temp:
if room[r][c] < K:
all_good = False
break
# 종료 조건
if all_good or choco > 100:
break
# 결과 출력
print(choco)