코딩테스트/Java

[JAVA] 백준 마법사 상어와 비바라기

SK_MOUSE 2021. 9. 23. 23:39

경계값 넘어설떄 오버플로우/언더플로우값 처리 방법은 아래 링크참고

https://skmouse.tistory.com/entry/JAVA-%EB%B0%B1%EC%A4%80-%EB%A7%88%EB%B2%95%EC%82%AC-%EC%83%81%EC%96%B4%EC%99%80-%ED%8C%8C%EC%9D%B4%EC%96%B4%EB%B3%BC

 

[JAVA] 백준 마법사 상어와 파이어볼

이틀만에 성공했다... grid는 x,y를 row col을 이처럼 적용해야된다. 보통 (r,c)로 주어지니 (y,x)로 받아야한다!! 우선 아래 코드에서는 x,y값을 반대로 적용했다. 그래서 문제 푸는내내 계속 헷갈렸다.

skmouse.tistory.com

 

구현문제였다.

(소요시간 : 2시간)

 

단순 구현문제였는데, N값의 경계값을 넘어가는 방식에 대해서 수학적으로 고민하다가 시간이 많이 흘렀다.

 

위 방법을 숙지해놓는것이 도움이 될 것같다.

 

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

public class Main {
    static int N, M;
    static int[][] a;
    static int[] d, s;
    static int[] dirR = {0,0, -1, -1, -1, 0, 1, 1, 1};
    static int[] dirC = {0,-1, -1, 0, 1, 1, 1, 0, -1};
    static Deque<Cloud> clouds = new LinkedList<>();
    static Deque<Cloud> REMOVEDclouds = new LinkedList<>();

    static class Cloud {
        int r, c;

        Cloud(int r, int c) {
            this.r = r;
            this.c = c;
        }

        void move(int d, int s) {
            r = r+ (s%N) * dirR[d];
            c = c +(s%N) * dirC[d];
            if (r > N) r = r % N;//업오버플로우
            if (r < 1) r = N - Math.abs(r);//다운오버플로우

            if (c > N) c = c % N;//업오버플로우
            if (c < 1) c = N - Math.abs(c);//다운오버플로우
        }
    }

    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());

        a = new int[N + 1][N + 1];
        d = new int[M];
        s = new int[M];
        for (int r = 1; r <= N; r++) {
            st = new StringTokenizer(br.readLine());
            for (int c = 1; c <= N; c++) {
                a[r][c] = Integer.parseInt(st.nextToken());
            }
        }
        for (int m = 0; m < M; m++) {
            st = new StringTokenizer(br.readLine());
            d[m] = Integer.parseInt(st.nextToken());
            s[m] = Integer.parseInt(st.nextToken());
        }
        //(N, 1), (N, 2), (N-1, 1), (N-1, 2)에 비구름이 생긴다.
        clouds.add(new Cloud(N, 1));
        clouds.add(new Cloud(N, 2));
        clouds.add(new Cloud(N - 1, 1));
        clouds.add(new Cloud(N - 1, 2));

        for (int m = 0; m < M; m++) {
            moves(d[m], s[m]);
        }
        int sum=0;
        for(int r=1; r<=N; r++) {
            for (int c = 1; c <= N; c++) {
                sum+=a[r][c];
            }
        }
        System.out.println(sum);
    }

    static int[][] nonRC;

    static void moves(int d, int s) {
        int size = clouds.size();
        for (int sz = 0; sz < size; sz++) {
            Cloud cld = clouds.remove();
            cld.move(d, s);
            a[cld.r][cld.c]++;


            REMOVEDclouds.add(cld);
        }


        int rdsize = REMOVEDclouds.size();
        nonRC = new int[rdsize][2];
        for (int rsz = 0; rsz < rdsize; rsz++) {
            Cloud cld = REMOVEDclouds.remove();
            waterCheck(cld.r, cld.c);

            nonRC[rsz][0] = cld.r;
            nonRC[rsz][1] = cld.c;
        }
        for (int r = 1; r <= N; r++) {
            for (int c = 1; c <= N; c++) {
                boolean checker = false;
                checker = notRemovedLoc(r, c);
                if (a[r][c] >= 2 && checker) {
                    a[r][c] -= 2;
                    clouds.add(new Cloud(r, c));
                }
            }
        }

    }

    static boolean notRemovedLoc(int r, int c) {
        for (int[] rc : nonRC)
            if (rc[0] == r && rc[1] == c) return false;//전에 건드렸던 구름이라면 거짓

        return true;
    }

    static void waterCheck(int r, int c) {
        int count = 0;
        //왼위
        int checkR = r - 1;
        int checkC = c - 1;
        if (boundaryCheck(checkR, checkC)) count++;
        //오위
        checkR = r - 1;
        checkC = c + 1;
        if (boundaryCheck(checkR, checkC)) count++;
        //왼아래
        checkR = r + 1;
        checkC = c - 1;
        if (boundaryCheck(checkR, checkC)) count++;
        //오른아래
        checkR = r + 1;
        checkC = c + 1;
        if (boundaryCheck(checkR, checkC)) count++;

        a[r][c] += count;
    }

    static boolean boundaryCheck(int r, int c) {
        if (r > 0 && c > 0 && r <= N && c <= N) {
            return a[r][c] >= 1;
        }

        return false;
    }
}
반응형

'코딩테스트 > Java' 카테고리의 다른 글

[JAVA] 백준 경사로  (0) 2021.09.28
(2021 카카오) 합승 택시 요금 JAVA  (0) 2021.09.24
[JAVA] 백준 사다리 조작  (0) 2021.09.16
(2021 카카오) 광고삽입 JAVA  (0) 2021.09.11
[JAVA] 백준 주사위 윷놀이  (0) 2021.09.01