코딩테스트/Java

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

SK_MOUSE 2021. 4. 29. 17:25
반응형

이틀만에 성공했다...

 

grid는 x,y를 row col을 이처럼 적용해야된다.

 

보통 (r,c)로 주어지니 (y,x)로 받아야한다!!

(r,c)로 주어지면 (y,x)로 받아야함.

 

우선 아래 코드에서는 x,y값을 반대로 적용했다.

r,c 를 x,y에 받으면 생기는 일

그래서 문제 푸는내내 계속 헷갈렸다.

 

 

가장 큰 실수는 

잘못된 부분은 아래에 정리하겠다.

import java.util.*;

class Main {
    public static int N, M, K;
    public static ArrayList<ArrayList<Queue<Fireball>>> fireball;
    public static int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
    public static int[] dy = {0, 1, 1, 1, 0, -1, -1, -1};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        M = sc.nextInt();
        K = sc.nextInt();
        fireball = new ArrayList<>();
        for (int i = 0; i <= N; i++) {//0~N
            fireball.add(new ArrayList<>());
            for (int j = 0; j <= N; j++) fireball.get(i).add(new LinkedList<>());//0~N
        }
        for (int i = 0; i < M; i++) {
            int r = sc.nextInt();
            int c = sc.nextInt();
            int m = sc.nextInt();
            int s = sc.nextInt();
            int d = sc.nextInt();
            fireball.get(r).get(c).offer(new Fireball(m, s, d));
        }
        //input끝
        for (int k = 0; k < K; k++) {
            //System.out.println("kkkkkkkkkk" + k);
            move(k);//이동
            // System.out.println("split");
            sumSplit(k);
        }

        System.out.println(print());
    }

    static int print() {
        int sum = 0;
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                while (!fireball.get(i).get(j).isEmpty()) {
                    Fireball b = fireball.get(i).get(j).poll();
                    sum += b.m;
                    //System.out.println("안뽀개진거:"+i+","+j);
                }
            }
        }
        return sum;
    }

    static class Fireball {
        int m, s, d;
        int kcount = 0;

        Fireball(int m, int s, int d) {
            this.m = m;//질량
            this.s = s;//몇칸이동
            this.d = d;//방향
        }

        Fireball(int m, int s, int d, int k) {
            this.kcount = k;
            this.m = m;//질량
            this.s = s;//몇칸이동
            this.d = d;//방향
        }
    }

    static void move(int k) {
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                if (fireball.get(i).get(j).isEmpty()) continue;
                int size = fireball.get(i).get(j).size();
                for (int s = 0; s < size; s++) {
                    Fireball b = fireball.get(i).get(j).poll();
                    if (b.kcount > k) {
                        fireball.get(i).get(j).offer(b);
                        continue;//이미 k번째
                    } else {//현위치 i,j
                        //System.out.print("(" + i + "," + j + ")");
                        b.kcount += 1;
                        int x = i + ((b.s % N) * dx[b.d]);
                        int y = j + ((b.s % N) * dy[b.d]);

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

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

                        fireball.get(x).get(y).offer(b);

                        //System.out.println("->(" + x + "," + y + ")"+b.d);
                    }
                }
            }
        }
    }

    static void sumSplit(int k) {
        ++k;
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                int size = fireball.get(i).get(j).size();
                if (size >= 2) {//2이상이면 합쳐
                    int split_m = 0, split_s = 0, split_d = 0;
                    for (int sz = 0; sz < size; sz++) {
                        Fireball b = fireball.get(i).get(j).poll();
                        split_m += b.m;
                        split_d += b.d % 2;
                        split_s += b.s;
                    }
                    split_m = split_m / 5;
                    if (split_m == 0) {
                        //System.out.println("뽀각");
                        continue;
                    }
                    //질량0이면 패스------------
                    split_s = split_s / size;
                    //System.out.println("s:" + split_s);
                    if (split_d == size || split_d == 0) {//모두 홀수(2n+2k+2l)+size거나 짝수 0246
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 0, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 2, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 4, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 6, k));
                    } else {//1357
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 1, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 3, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 5, k));
                        fireball.get(i).get(j).offer(new Fireball(split_m, split_s, 7, k));
                    }
                }
            }
        }
    }
}

하이라이트부분.

1~N을 초과/미만인 좌표는 서로 연결된다.

즉, 그리드 인덱스 오버플로우시 0=>N으로, N+1=>1로 바꿔주라는 뜻이다.

 

이 부분에서 mod연산을 하는 와중 실수가 계속되었다.

해결에 도움을 준 질문/답변자에게 감사의 링크를 남긴다.(www.acmicpc.net/board/view/66407)

int x = i + ((b.s % N) * dx[b.d]);
int y = j + ((b.s % N) * dy[b.d]);

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

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

fireball.get(x).get(y).offer(b);

나는 내가 mod연산을 잘 했다고 생각했는데, 다른방식으로 다시 연산하니 성공하였다.

아마 계산해보지 못한 경우의 수가 남아있던 것 같다.

 

두가지 추가 테스트케이스를 남겨두겠다.

4 6 4
1 1 5 1 1
3 3 5 1 5
1 3 5 1 3
3 1 5 1 7
2 2 5 1 3
3 2 5 1 2

-> 4

 

4 9 5
3 2 8 5 2
3 3 19 3 4
3 1 7 1 1
4 4 6 4 0
2 1 6 2 5
4 3 9 4 3
2 2 16 1 2
4 2 17 5 3
3 4 3 5 7

-> 33

반응형

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

[JAVA] 백준 연구소 DFS+BFS  (3) 2021.05.10
[JAVA] 백준 후위표기식  (0) 2021.05.04
[JAVA] 백준 아기상어  (0) 2021.04.28
[JAVA] 조합 DP로 풀기 : 백준 다리놓기  (0) 2021.04.21
[JAVA] 백준 로봇청소기  (0) 2021.04.14