본문 바로가기
Tech/Coding

17144번: 미세먼지 안녕!(OOP 문제 해결)

by redcubes 2025. 6. 17.

https://www.acmicpc.net/problem/17144

파이썬 객체지향으로 푸는 공기청정기 시뮬레이션 문제

1. 문제 구조 요약

방은 R×C 격자로 이루어져 있고, 공기청정기가 설치된 두 칸을 기준으로 미세먼지가 확산되고 정화되는 시뮬레이션이 T초 동안 반복된다.

2. 객체지향 접근 이유

  • 격자 상태를 멤버 변수로 유지
  • 확산, 정화 기능을 메서드로 모듈화
  • 공기청정기의 위치를 캡슐화하여 코드 안정성 확보

3. Room 클래스 구조

3.1 생성자 및 공기청정기 위치 확인


class Room:
    def __init__(self, R, C, T, grid):
        self.R, self.C, self.T = R, C, T
        self.grid = grid
        self.cleaner = self._find_cleaner()

    def _find_cleaner(self):
        for r in range(self.R):
            if self.grid[r][0] == -1:
                return (r, r + 1)

3.2 시뮬레이션 수행


    def simulate(self):
        for _ in range(self.T):
            self._spread()
            self._purify()

3.3 미세먼지 확산 구현


    def _spread(self):
        temp = [[0] * self.C for _ in range(self.R)]
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

        for r in range(self.R):
            for c in range(self.C):
                if self.grid[r][c] > 0:
                    amount = self.grid[r][c] // 5
                    cnt = 0
                    for dr, dc in directions:
                        nr, nc = r + dr, c + dc
                        if 0 <= nr < self.R and 0 <= nc < self.C and self.grid[nr][nc] != -1:
                            temp[nr][nc] += amount
                            cnt += 1
                    self.grid[r][c] -= amount * cnt

        for r in range(self.R):
            for c in range(self.C):
                self.grid[r][c] += temp[r][c]

3.4 공기청정기 작동


    def _purify(self):
        upper, lower = self.cleaner
        self._circulate_upper(upper)
        self._circulate_lower(lower)

3.5 위쪽 공기청정기 (반시계)


    def _circulate_upper(self, r):
        for i in range(r-1, 0, -1):
            self.grid[i][0] = self.grid[i-1][0]
        for i in range(self.C-1):
            self.grid[0][i] = self.grid[0][i+1]
        for i in range(r):
            self.grid[i][self.C-1] = self.grid[i+1][self.C-1]
        for i in range(self.C-1, 1, -1):
            self.grid[r][i] = self.grid[r][i-1]
        self.grid[r][1] = 0

3.6 아래쪽 공기청정기 (시계)


    def _circulate_lower(self, r):
        for i in range(r+1, self.R-1):
            self.grid[i][0] = self.grid[i+1][0]
        for i in range(self.C-1):
            self.grid[self.R-1][i] = self.grid[self.R-1][i+1]
        for i in range(self.R-1, r, -1):
            self.grid[i][self.C-1] = self.grid[i-1][self.C-1]
        for i in range(self.C-1, 1, -1):
            self.grid[r][i] = self.grid[r][i-1]
        self.grid[r][1] = 0

3.7 남은 미세먼지 합산


    def dust_total(self):
        return sum(sum(cell for cell in row if cell > 0) for row in self.grid)

4. 전체 코드


class Room:
    def __init__(self, R, C, T, grid):
        self.R, self.C, self.T = R, C, T
        self.grid = grid
        self.cleaner = self._find_cleaner()

    def _find_cleaner(self):
        for r in range(self.R):
            if self.grid[r][0] == -1:
                return (r, r + 1)

    def simulate(self):
        for _ in range(self.T):
            self._spread()
            self._purify()

    def _spread(self):
        temp = [[0] * self.C for _ in range(self.R)]
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

        for r in range(self.R):
            for c in range(self.C):
                if self.grid[r][c] > 0:
                    amount = self.grid[r][c] // 5
                    cnt = 0
                    for dr, dc in directions:
                        nr, nc = r + dr, c + dc
                        if 0 <= nr < self.R and 0 <= nc < self.C and self.grid[nr][nc] != -1:
                            temp[nr][nc] += amount
                            cnt += 1
                    self.grid[r][c] -= amount * cnt

        for r in range(self.R):
            for c in range(self.C):
                self.grid[r][c] += temp[r][c]

    def _purify(self):
        upper, lower = self.cleaner
        self._circulate_upper(upper)
        self._circulate_lower(lower)

    def _circulate_upper(self, r):
        for i in range(r-1, 0, -1):
            self.grid[i][0] = self.grid[i-1][0]
        for i in range(self.C-1):
            self.grid[0][i] = self.grid[0][i+1]
        for i in range(r):
            self.grid[i][self.C-1] = self.grid[i+1][self.C-1]
        for i in range(self.C-1, 1, -1):
            self.grid[r][i] = self.grid[r][i-1]
        self.grid[r][1] = 0

    def _circulate_lower(self, r):
        for i in range(r+1, self.R-1):
            self.grid[i][0] = self.grid[i+1][0]
        for i in range(self.C-1):
            self.grid[self.R-1][i] = self.grid[self.R-1][i+1]
        for i in range(self.R-1, r, -1):
            self.grid[i][self.C-1] = self.grid[i-1][self.C-1]
        for i in range(self.C-1, 1, -1):
            self.grid[r][i] = self.grid[r][i-1]
        self.grid[r][1] = 0

    def dust_total(self):
        return sum(sum(cell for cell in row if cell > 0) for row in self.grid)


if __name__ == "__main__":
    import sys
    input = sys.stdin.read
    data = input().split()

    R, C, T = map(int, data[:3])
    grid = [list(map(int, data[i*C+3:(i+1)*C+3])) for i in range(R)]

    room = Room(R, C, T, grid)
    room.simulate()
    print(room.dust_total())

5. 결론

이 문제는 격자 상태를 지속적으로 변경하며 시뮬레이션하는 문제로, 객체지향 프로그래밍(OOP)을 적용했을 때 구조적으로 분명하고 유지보수도 쉬워진다. 각 기능을 메서드로 분리하고 상태를 캡슐화함으로써 복잡도를 줄이고 디버깅과 기능 확장이 수월해진다.

 

 

'Tech > Coding' 카테고리의 다른 글

도깨비말(Pig Latin)  (0) 2025.06.23
색칠 공부  (0) 2025.06.22
회문 끝말잇기  (0) 2025.06.02
SciComLove (2023)  (0) 2025.05.27
ROPE 자료구조: 구조와 동작 원리(Python 예제)  (0) 2025.05.24