알고리즘/백준

[백준] 17144번: 미세먼지 안녕!

Ynghan 2024. 1. 15. 22:36

문제 이해

R(행) × C(열)을 입력으로 받고, T(초)를 입력받는다.

R × C 크기 만큼의 숫자를 입력 받는다.

이때, 1번 째 열에 공기청정기가 설치되고 -1로 나타낸다.

 

확산

확산 전 / 확산 후

순환

순환 전 / 순환 후

 

문제 풀기

from sys import stdin
from typing import List

ccw = globals()

def rotate(A: List[List[int]]) -> List[List[int]]:
    for i in range(ccw-2, -1, -1):
        A[i+1][0] = A[i][0]

    for i in range(0,C,1):
        A[0][i] = A[0][i+1]

    for i in range(0,ccw):
        A[i][-1] = A[i+1][-1]

    for i in range(C,1,-1):
        A[ccw][i] = A[ccw][i-1]

    A[ccw][0] = -1
    A[cw][0] = -1

    return A

def spread(A: List[List[int]]) -> List[List[int]]:
    # 상 하 좌 우
    x = [0, 0, -1, 1]
    y = [1, -1, 0, 0]

    new_A = List[List[int]]

    for i in range(R):
        for j in range(C):
            if A[i][j] == 0:
                continue
            for k in range(4):
                if R > i + x[k] >= 0 and j + y[k] <= C and i + x[k] != ccw and j + y[k] != 0:
                    new_A[i + x[k]][j + y[k]] = A[i][j] // 5
                    A[i][j] -= new_A[i + x[k]][j + y[k]] // 5
    A += new_A

    return A

input = stdin.readline

R, C, T = map(int, input().split())

A = [list(map(int, input().split())) for _ in range(R)]

ccw = 0
for i in range(R):
    if A[i][0] == -1:
        ccw = i
        break
cw = ccw - 1

for _ in range(T):
    spread(A)
    rotate(A)

total = sum(A)

print(total)
  • 순환을 위한 rotate 메소드
  • 확산을 위한 spread 메소드

코드 수정

전체 구조 코드

수정 전

R, C, T = map(int, input().split())

A = [list(map(int, input().split())) for _ in range(R)]

ccw = 0
for i in range(R):
    if A[i][0] == -1:
        ccw = i
        break
cw = ccw - 1

for _ in range(T):
    spread(A)
    rotate(A)

total = sum(A)

print(total)

수정 후 

r, c, t = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(r)]
for i in range(r):
    if board[i][0] == -1:
        ccw, cw = i, i + 1
        break
for _ in range(t):
    board = spread()
    rotate()
print(sum([sum(line) for line in board]) + 2) # 공기청정기 -1 * 2 고려
- 변수명 변경 : A → board
- ccw, cw 대입 방식 변경
- spread() 함수는 board를 따로 생성하지 않고 반환하기 때문에 board에 직접 대입
- 2차원 배열 매개변수로 사용 → 매개 변수 없이 메소드 호출
- 잘못된 집계 함수 방식 수정

spread(확산) 메소드

수정 전

def spread(A: List[List[int]]) -> List[List[int]]:
    # 상 하 좌 우
    x = [0, 0, -1, 1]
    y = [1, -1, 0, 0]

    new_A = List[List[int]]

    for i in range(R):
        for j in range(C):
            if A[i][j] == 0:
                continue
            for k in range(4):
                if R > i + x[k] >= 0 and j + y[k] <= C and i + x[k] != ccw and j + y[k] != 0:
                    new_A[i + x[k]][j + y[k]] = A[i][j] // 5
                    A[i][j] -= new_A[i + x[k]][j + y[k]] // 5
    A += new_A

    return A

수정 후

def spread():
    """
    미세 먼지 확산 결과 반환 함수
    """
    dx = [1, -1, 0, 0]
    dy = [0, 0, 1, -1]
    new_board = [[0] * c for _ in range(r)]
    new_board[ccw][0] = -1
    new_board[cw][0] = -1
    for x in range(r):
        for y in range(c):
            if board[x][y] > 0:
                new_board[x][y] += board[x][y]
                for d in range(4):
                    nx = x + dx[d]
                    ny = y + dy[d]
                    if 0 <= nx < r and 0 <= ny < c and board[nx][ny] != -1:
                        new_board[nx][ny] += board[x][y] // 5
                        new_board[x][y] -= board[x][y] // 5
    return new_board
- 변수명 : new_A → new_board
- 공기 청정기 위치 설정 : new_board[ccw][0] = -1 ....
- new_board에 확산된 값만 넣도록 했음 → new_board에 기존 값을 더한 이후 확산 값을 계산하도록 했음
- 반복문 변수를 x와 y로 사용함 → 가독성
- 기존 코드는 0 이외의 값을 필터링하지 못하여 공기 청정기를 필터링 하지 못하였다. 수정된 코드는 0 초과의 값만 필터링하여 공기 청정기를 필터링할 수 있게 하였다.

rotate() 메소드

수정 전

def rotate(A: List[List[int]]) -> List[List[int]]:
    for i in range(ccw-2, -1, -1):
        A[i+1][0] = A[i][0]

    for i in range(0,C,1):
        A[0][i] = A[0][i+1]

    for i in range(0,ccw):
        A[i][-1] = A[i+1][-1]

    for i in range(C,1,-1):
        A[ccw][i] = A[ccw][i-1]

    A[ccw][0] = -1
    A[cw][0] = -1

    return A

수정 후 

def rotate():
    """
    미세 먼지 순환 함수
    """
    # 위쪽 순환: 반시계 방향
    for x in range(ccw - 1, 0, -1):
        board[x][0] = board[x - 1][0]
    for y in range(c - 1):
        board[0][y] = board[0][y + 1]
    for x in range(ccw):
        board[x][-1] = board[x + 1][-1]
    for y in range(c - 1, 0, -1):
        board[ccw][y] = board[ccw][y - 1]

    # 아래쪽 순환: 시계 방향
    for x in range(cw + 1, r - 1):
        board[x][0] = board[x + 1][0]
    for y in range(c - 1):
        board[-1][y] = board[-1][y + 1]
    for x in range(r - 1, cw, -1):
        board[x][-1] = board[x - 1][-1]
    for y in range(c - 1, 0, -1):
        board[cw][y] = board[cw][y - 1]

    # 공기청정기에서 나온 바람은 미세 먼지가 없는 바람이므로 0으로 초기화
    board[ccw][1] = 0
    board[cw][1] = 0
위쪽 순환만 코드 작성했었음.
공기청정기에서 나오는 바람을 생각하지 못하였음.

매우 틀린 부분이 많았다.