[BOJ]17144. 미세먼지 안녕!
2024. 8. 28. 20:40ㆍ[Algorithm]/문제 풀이
문제
https://www.acmicpc.net/problem/17144
사용 알고리즘
구현, 시뮬레이션
풀이
고려사항
1. 먼지 확산 - 확산하는 곳이 공기청정기인지, 범위를 넘어가는 곳이 아닌지
2. 공기 청정 - 방향전환, 먼지 이동 시 갱신 된 값과 이전 값 구분
후기
1. 이 문제에서 어려운 점은 공기 청정 값 갱신이였다.
아래 코드는 새로운 배열을 생성한 후 값을 옮기는 방식을 채택했다.
하지만 공기 청정하는 라인의 값은 갱신되지만,
그 외의 원래 가지고 있어야하는 값이 0으로 나와 사용할 수 없었다.
이러한 방식을 사용하려면 새로운 배열을 0이 아닌 원래 배열에서 deepcopy하여 사용해야 한다.
# 잘못된 공기청정 로직
def refresh(room):
after_room = [[0] * C for _ in range(R)]
# 가로 확산
for i in range(1, C):
after_room[0][i - 1] = room[0][i]
after_room[air_purifier][i] = room[air_purifier][i - 1]
after_room[air_purifier + 1][i] = room[air_purifier + 1][i - 1]
after_room[R - 1][i - 1] = room[R - 1][i]
# 세로 확산
for j in range(air_purifier):
after_room[j + 1][0] = room[j][0]
after_room[j][C - 1] = room[j + 1][C - 1]
for k in range(air_purifier + 1, R - 1):
after_room[k][0] = room[k + 1][0]
after_room[k + 1][C - 1] = room[k][C - 1]
return after_room
2. 위의 방식은 끼워맞춘 느낌이 강하고 범위를 고려하기 어려워
didj를 활용한 방향 전환방식으로 변환하여 코드를 수정했다.
이때, 고려해야 할 점은
1) 원래 자리인 공기청정 자리로 돌아온 경우 값을 갱신하는 것이 아니라
끝임을 인지하고 루프를 나와야한다.
2) 또한, 벽을 만났을 때 방향전환 후 값을 변경하지 않고 넘어가야한다.
3) 방향전환 후 값 변경을 시도하면 IndexError(Out of Range)가 발생한다.
4) 마지막으로, 값 변경 후 현재 위치를 변경해주어야 한다.(ci, cj = ni, nj)
코드
import sys
input = sys.stdin.readline
didj = [[0, 1], [-1, 0], [0, -1], [1, 0]]
def diffusion(room):
after_room = [[0] * C for _ in range(R)]
for i in range(R):
for j in range(C):
# 공기청정기
if room[i][j] == -1:
after_room[i][j] = -1
# 미세먼지
elif room[i][j] != 0:
diffusion_air = room[i][j] // 5
diffusion_cnt = 0
for di, dj in didj:
ni, nj = i + di, j + dj
if 0 <= ni < R and 0 <= nj < C and room[ni][nj] != -1:
after_room[ni][nj] += diffusion_air
diffusion_cnt += 1
after_room[i][j] += room[i][j] - (diffusion_air * diffusion_cnt)
return after_room
def refresh(room):
# 시계 반대방향 회전
lo, temp = 0, 0
ci, cj = air_purifiers[0], 0
while True:
ni, nj = ci + didj[lo][0], cj + didj[lo][1]
# 공기청정기로 돌아온 경우
if ni == air_purifiers[0] and nj == 0:
break
# 방향회전 필요한 경우
if ni == R or nj == C or ni == -1 or nj == -1:
lo = (lo + 1) % 4
continue
# 값 변경
room[ni][nj], temp = temp, room[ni][nj]
ci, cj = ni, nj
# 시계 방향 회전
lo, temp = 0, 0
ci, cj = air_purifiers[1], 0
while True:
ni, nj = ci + didj[lo][0], cj + didj[lo][1]
# 공기청정기로 돌아온 경우
if ni == air_purifiers[1] and nj == 0:
break
# 방향회전 필요한 경우
if ni == R or nj == C or ni == -1 or nj == -1:
lo = (lo - 1) % 4
continue
# 값 변경
room[ni][nj], temp = temp, room[ni][nj]
ci, cj = ni, nj
return room
R, C, T = map(int, input().split())
room = [list(map(int, input().split())) for _ in range(R)]
air_purifiers = [i for i in range(R) if room[i][0] == -1]
for _ in range(T):
room = refresh(diffusion(room))
dust = 2
for i in range(R):
dust += sum(room[i])
print(dust)
결과
'[Algorithm] > 문제 풀이' 카테고리의 다른 글
[BOJ]1806. 부분합 (0) | 2024.09.09 |
---|---|
[BOJ]5636. 소수 부분 문자열 (0) | 2024.09.09 |
[BOJ]9465. 스티커 (9) | 2024.08.28 |
[BOJ]2638. 치즈 (0) | 2024.08.27 |
[BOJ]14226 : 이모티콘 (0) | 2024.08.26 |