728x90
# 조건
- 미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다.
- 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다.
- 구사과는 뛰어난 코딩 실력을 이용해 각 칸 (r, c)에 있는 미세먼지의 양을 실시간으로 모니터링하는 시스템을 개발했다. (r, c)는 r행 c열을 의미한다.
- 공기청정기는 항상 1번 열에 설치되어 있고, 크기는 두 행을 차지한다.
- 공기청정기가 설치되어 있지 않은 칸에는 미세먼지가 있고, (r, c)에 있는 미세먼지의 양은 Ar,c이다.
1초 동안 아래 적힌 일이 순서대로 일어난다.
- 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
- (r, c)에 있는 미세먼지는 인접한 네 방향으로 확산된다.
- 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다.
- 확산되는 양은 Ar,c/5이고 소수점은 버린다.
- (r, c)에 남은 미세먼지의 양은 Ar,c - (Ar,c/5)×(확산된 방향의 개수) 이다.
- 공기청정기가 작동한다.
- 공기청정기에서는 바람이 나온다.
- 위쪽 공기청정기의 바람은 반시계방향으로 순환하고, 아래쪽 공기청정기의 바람은 시계방향으로 순환한다.
- 바람이 불면 미세먼지가 바람의 방향대로 모두 한 칸씩 이동한다.
- 공기청정기에서 부는 바람은 미세먼지가 없는 바람이고, 공기청정기로 들어간 미세먼지는 모두 정화된다.
아래는 확산의 예시
공기청정기의 순환
# 접근 방법
- 주어진 규칙에 따라 먼지를 확산시키고, 이동시키면 된다.
- 확신시키는 diffusion함수, 공기청정기를 이동 시키는 move_first, move_second함수를 구현해줄 것이다.
- 우선 확산시킬 때 동시에 모든 미세 먼지가 확산을 시키므로 확산된 값을 저장해줄 temp_arr을 만들어 주고 deepcopy를 통하여 원본 배열과 함께 인자로 넘겨준다.
- 원본 배열에 값이 존재한다면 => 미세 먼지가 있다면
- 규칙에 따라 확산 가능한 주변 칸이 있다면 임시 배열에 arr[i][j] // 5를 더해준다.
- 4방향 탐색이 끝난 후 확산 시킨 칸도 arr[i][j] - (arr[i][j]//5) * cnt를 임시 배열에 더해준다.
- 모든 미세먼지의 확산이 끝났다면 확산이 완료된 임시 배열을 return 해준다.
- return 받은 임시 배열과 움직이는 방향을 인자로 move함수를 실행시켜주고, 이동이 완료된 배열을 원본 배열에 다시 저장해준다.
import sys
sys.stdin = open('input.txt')
input = sys.stdin.readline
from copy import deepcopy
def solve():
# 미세먼지 확산
def diffusion(temp_arr, arr):
for i in range(R):
for j in range(C):
if arr[i][j] and (i, j) not in air:
# 현재 좌표에서 확산 시킨 칸의 개수
# 확산시키는 칸의 // 5로 임시 배열에 더해주기
cnt = 0
val = arr[i][j] // 5
for d in range(4):
ni, nj = i + di[d], j + dj[d]
if 0<=ni<R and 0<=nj<C and arr[ni][nj] != -1:
temp_arr[ni][nj] += val
cnt += 1
temp_arr[i][j] += arr[i][j] - (val * cnt)
if arr[i][j] == -1:
temp_arr[i][j] = -1
return temp_arr
# 첫 번째 공기 청정기 => 상 우 하 좌로 돌면서 다음 좌표 복사해주기
def move_first(dx, dy, start, arr):
si, sj = start[0], start[1]
# 각 모서리 도착 따른 조건 분기 해주기
for d in range(4):
while 0<=si<R and 0<=sj<C:
if d == 0:
if not si == 0:
arr[si][sj] = arr[si-1][sj]
else: break
elif d == 1:
if not sj == C-1:
arr[si][sj] = arr[si][sj+1]
else: break
elif d == 2:
if not si == start[0]:
arr[si][sj] = arr[si+1][sj]
else: break
elif d == 3:
if not sj == 1:
arr[si][sj] = arr[si][sj-1]
else: break
si += dx[d]
sj += dy[d]
# 출발지점 -1로 다시 표시
arr[si][sj] = 0
arr[si][sj-1] = -1
return arr
# 2번째 공기청정기 => 하 우 상 좌로 순회하면서 다음 좌표의 값 복사해주기
def move_second(dx, dy, start, arr):
si, sj = start[0], start[1]
# 각 모서리 도착 따른 조건 분기 해주기
for d in range(4):
while 0<=si<R and 0<=sj<C:
if d == 0:
if not si == R-1:
arr[si][sj] = arr[si+1][sj]
else:
break
elif d == 1:
if not sj == C-1:
arr[si][sj] = arr[si][sj+1]
else: break
elif d == 2:
if not si == start[0]:
arr[si][sj] = arr[si-1][sj]
else: break
elif d == 3:
if not sj == 1:
arr[si][sj] = arr[si][sj-1]
else: break
si += dx[d]
sj += dy[d]
# 출발지점 -1로 다시 표시
arr[si][sj] = 0
arr[si][sj-1] = -1
return arr
R, C, T = map(int, input().split())
room = [[*map(int, input().split())] for _ in range(R)]
air = []
di, dj = [-1, 1, 0, 0], [0, 0, 1, -1]
for i in range(R):
for j in range(C):
if room[i][j] == -1:
air.append((i, j))
temp = [[0] * C for _ in range(R)]
for _ in range(T):
# 미세먼지 확산에 원본 배열 넣고 확산시킨 확산된 배열 리턴 받기
diff_arr = diffusion(deepcopy(temp), room)
# 리턴 받은 확산된 배열 공기청정기로 먼지 이동시키고 원본 배열에 다시 저장해주기.
# 공기청정기 움직이는 건 시계 방향으로 해주면서 배열에 복사
# 위쪽 공기청정기와 아래쪽 공기청정기 움직이는 순서 인자로 넘겨주기
room = move_first([-1, 0, 1, 0], [0, 1, 0, -1], air[0], diff_arr)
room = move_second([1, 0, -1, 0], [0, 1, 0, -1], air[1], room)
result = 0
for i in room:
result += sum(i)
print(result+2)
solve()
728x90
'ALGORITHM > 정렬, 탐색,구현' 카테고리의 다른 글
[백준 1254번] 파이썬 - 팰린드롬 만들기 (2) | 2023.09.06 |
---|---|
[백준 1300번] 파이썬 - K번째 수 (0) | 2023.09.04 |
[백준 12871번] 파이썬 - 무한 문자열 (0) | 2023.08.31 |
[백준 2900번] 파이썬 - 프로그램 (0) | 2023.08.31 |
[백준 14921번] 파이썬 - 용액 합성하기 (0) | 2023.08.28 |