백준 20165 인내의 도미노 장인 호석 (Java,자바)

jonghyukLee·2022년 3월 8일
0

이번에 풀어본 문제는
백준 20165번 인내의 도미노 장인 호석 입니다.

📕 문제 링크

❗️코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

class Point
{
    int x,y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Main {
    static int N,M,R;
    static int [][] map;
    static char [][] domino;
    static int [] dx = {-1,1,0,0};
    static int [] dy = {0,0,-1,1};
    static int answer;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());

        map = new int[N+1][M+1];
        domino = new char[N+1][M+1];

        // 도미노 초기화
        for(int i = 1; i <= N; ++i)
        {
            Arrays.fill(domino[i],'S');
        }

        for(int i = 1 ; i <= N; ++i)
        {
            st = new StringTokenizer(br.readLine());
            for(int j = 1; j <= M; ++j)
            {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        while(R-- > 0)
        {
            st = new StringTokenizer(br.readLine());
            int atkX = Integer.parseInt(st.nextToken());
            int atkY = Integer.parseInt(st.nextToken());
            int dir = getDir(st.nextToken().charAt(0));

            st = new StringTokenizer(br.readLine());
            int defX = Integer.parseInt(st.nextToken());
            int defY = Integer.parseInt(st.nextToken());

            // 서있는 도미노를 선택했다면 공격.
            if(domino[atkX][atkY] == 'S')
            {
                domino[atkX][atkY] = 'F';
                answer += attack(atkX,atkY,dir);
            }

            // 수비
            domino[defX][defY] = 'S';
        }
        StringBuilder sb = new StringBuilder();
        sb.append(answer).append("\n");
        for(int i = 1; i <= N; ++i)
        {
            for(int j = 1; j <= M; ++j)
            {
                sb.append(domino[i][j]).append(" ");
            }
            sb.append("\n");
        }
        System.out.print(sb);
    }
    static int attack(int x, int y, int dir)
    {
        Queue<Point> q = new LinkedList<>();
        q.add(new Point(x,y));
        int res = 1;
        while(!q.isEmpty())
        {
            Point cur = q.poll();
            //도미노의 높이
           int curH = map[cur.x][cur.y];

           //높이 -1개 만큼 쓰러짐
            int mx = cur.x;
            int my = cur.y;
           for(int t = 1; t < curH; ++t)
           {
               mx += dx[dir];
               my += dy[dir];

               //범위를 벗어나면, 더이상 진행할필요 x
               if(!isValid(mx,my)) break;
               //이미 넘어져있다면 다음반복 , 높이에 따라 더 진행할 수도 있기때문
               if(domino[mx][my] == 'F') continue;
               domino[mx][my] = 'F';
               res++;
               q.add(new Point(mx,my));
           }
        }
        return res;
    }
    static int getDir(char c)
    {
        if(c == 'E') return 3;
        else if(c == 'W') return 2;
        else if(c == 'S') return 1;
        else return 0;
    }

    static boolean isValid(int x, int y)
    {
        return x > 0 && y > 0 && x <= N && y <= M;
    }

}

📝 풀이

구현 문제입니다.
공격자는 도미노를 쓰러뜨리고, 수비는 하나의 도미노를 세우는 행위가 한 라운드이며 최종적으로 공격자가 쓰러뜨린 도미노의 개수와 도미노의 상태를 출력하는 문제입니다.
공격자가 지정한 좌표의 도미노가 쓰러진 상태가 아니라면, 입력된 방향으로 도미노를 쓰러뜨립니다. 이때 시작 도미노를 제외하고 해당 도미노의 높이-1개가 나란히 쓰러지며, 쓰러진 각 도미노들도 높이를 지니고 있기 때문에, 위와 같은 로직을 수행하기 위해 큐에 모두 담아줍니다. 도미노가 쓰러질 때 마다 카운트를 올려주고, 마지막으로 이번 공격에서 쓰러진 도미노의 개수를 answer에 누적하기 위해 리턴해줍니다. 공격이 끝나고, 수비가 입력한 좌표의 도미노를 세워주면 한 라운드가 끝나게 됩니다. 위 두 과정을 R번 반복한 후 결과를 출력해주면 해결됩니다.

📜 후기

역시 저는 구현 문제가 재밌는거같아요..ㅋㅋㅋㅋ 즐기면서 풀 수 있었던 문제입니다!

profile
머무르지 않기!

0개의 댓글