[BOJ][C#] 17144 미세먼지 안녕!

LimJaeJun·2024년 1월 16일
0

PS/BOJ

목록 보기
100/108

📕 문제

📌 링크

📗 접근 방식

미세먼지 확산 및 공기청정기 순환을 T번 반복
미세먼지 확산:

  • 미세먼지 확산을 기록할 TempArray 하나 선언
  • 현재 grid에서 상하좌우를 판단하며 확산이 가능하면
    • 현재 grid의 미세먼지량 -= 현재 grid의 미세먼지량/5
    • 확산 가능한 위치의 미세먼지량 += 현재 grid의 미세먼지량/5

공기청정기 순환

  • 위쪽 공기청정기와 아래쪽 공기청정기의 위치를 알고 있어야한다.
    (처음에는 공기 청정기의 위치가 바뀔 수 있다고 생각해서 x, y를 모두 기록했었지만 문제에 1행에만 존재한다고 나와있었다... 문제 진짜 제대로 읽고 풀어야겠다..)
  • 위쪽 공기청정기를 먼저 순환시킨다.
    • 왼쪽, 위, 오른쪽, 아래 순으로 미세먼지량을 이동시킴
    • 마지막에 빈공간을 0으로 초기화
  • 아래쪽 공기청정기도 마찬가지
    • 왼쪽, 아래, 오른쪽, 위 순으로 미세먼지량을 이동시킴

출력

  • grid를 탐색하며 0보다 큰 수들을 합산한 결과를 출력한다.
    (주의 : 공기청정기의 값이 -1이므로 그냥 전부 더해버리면 값이 틀리게 나온다)

📘 코드

namespace BOJ  
{  
    static class Input<T>  
    {  
        public static T GetInput() => ConvertStringToType(Console.ReadLine());
        public static T[] GetInputArray() => Array.ConvertAll(Console.ReadLine().Split(), Input<T>.ConvertStringToType);

        public static T[,] GetInput2DArray(int r, int c)
        {
            var result = new T[r, c];

            for (int i = 0; i < r; i++)
            {
                var inputs = Input<T>.GetInputArray();
                for (int j = 0; j < c; j++)
                {
                    result[i, j] = inputs[j];
                }
            }
            
            return result;
        }
        
        private static T ConvertStringToType(string input) => (T)Convert.ChangeType(input, typeof(T));  
    }  
      
    class No_17144
    {
        static int R, C;
        static int[,] grid;
        static (int x, int y) airCleanerUp, airCleanerDown;

        static void Main()
        {
            // 입력 처리
            var inputs = Input<int>.GetInputArray();
            R = inputs[0];
            C = inputs[1];
            int T = inputs[2];

            grid = Input<int>.GetInput2DArray(R, C);

            bool isFirstAirCleanerFound = false;
            bool isSecondAirCleanerFound = false;
            for (int i = 0; i < R; i++)
            {
                for (int j = 0; j < C; j++)
                {
                    if (grid[i, j] != -1) continue;
                    
                    if (!isFirstAirCleanerFound)
                    {
                        airCleanerUp = (i, j);
                        isFirstAirCleanerFound = true;
                    }
                    else if (!isSecondAirCleanerFound)
                    {
                        airCleanerDown = (i, j);
                        isSecondAirCleanerFound = true;
                        break;
                    }
                }

                if (isSecondAirCleanerFound)
                    break;
            }
            
            // T번 시뮬레이션 수행
            while (T-- > 0)
            {
                SpreadDust();
                RunAirCleaner();
            }

            // 결과 출력
            int result = CalculateTotalDust();
            Console.WriteLine(result);
        }

        // 미세먼지 확산
        static void SpreadDust()
        {
            int[,] tempGrid = new int[R, C];

            Array.Copy(grid, tempGrid, grid.Length);

            int[] dr = { 1, 0, -1, 0 };
            int[] dc = { 0, 1, 0, -1 };

            for (int r = 0; r < R; r++)
            {
                for (int c = 0; c < C; c++)
                {
                    if (grid[r, c] <= 0) continue;
                    
                    int spreadAmount = grid[r, c] / 5;

                    for (int i = 0; i < 4; i++)
                    {
                        int nr = r + dr[i];
                        int nc = c + dc[i];

                        if (nr < 0 || nr >= R || nc < 0 || nc >= C) continue;
                        if (grid[nr, nc] == -1) continue;
                        
                        tempGrid[nr, nc] += spreadAmount;
                        tempGrid[r, c] -= spreadAmount;
                    }
                }
            }

            Array.Copy(tempGrid, grid, tempGrid.Length);
        }

        // 공기청정기 작동
        static void RunAirCleaner()
        {
            // 위쪽 공기청정기
            // 왼쪽
            for (int i = airCleanerUp.x - 1; i > 0; i--)
            {
                grid[i, 0] = grid[i - 1, 0];
            }
            // 위
            for (int i = 0; i < C - 1; i++)
            {
                grid[0, i] = grid[0, i + 1];
            }
            // 오른쪽
            for (int i = 1; i <= airCleanerUp.x; i++)
            {
                grid[i - 1, C - 1] = grid[i, C - 1];
            }
            // 아래
            for (int i = C - 1; i > 1; i--)
            {
                grid[airCleanerUp.x, i] = grid[airCleanerUp.x, i - 1];
            }

            grid[airCleanerUp.x, 1] = 0;

            // 아래쪽 공기청정기
            // 왼쪽
            for (int i = airCleanerDown.x + 1; i < R - 1; i++)
            {
                grid[i, 0] = grid[i + 1, 0];
            }
            // 아래
            for (int i = 0; i < C - 1; i++)
            {
                grid[R - 1, i] = grid[R - 1, i + 1];
            }
            // 오른쪽
            for (int i = R - 1; i >= airCleanerDown.x; i--)
            {
                grid[i, C - 1] = grid[i - 1, C - 1];
            }
            // 위
            for (int i = C - 1; i > 1; i--)
            {
                grid[airCleanerDown.x, i] = grid[airCleanerDown.x, i - 1];
            }

            grid[airCleanerDown.x, 1] = 0;
        }

        // 총 미세먼지 양 계산
        static int CalculateTotalDust()
        {
            int totalDust = 0;

            for (int r = 0; r < R; r++)
            {
                for (int c = 0; c < C; c++)
                {
                    if (grid[r, c] > 0)
                    {
                        totalDust += grid[r, c];
                    }
                }
            }

            return totalDust;
        }
    }
}

📙 오답노트

역시 구현&시뮬레이션이였다.. 꽤 걸리긴했지만 다행히 내가 생각한 로직을 구현해냈고 맞았다!
공기청정기 순환 시뮬레이션 구현하는게 조금 빡세긴했다.

📒 알고리즘 분류

  • 구현
  • 시뮬레이션
profile
Dreams Come True

0개의 댓글

관련 채용 정보