6 minute read

πŸ“Œ λ‚œμ΄λ„

πŸ₯‡ Gold 4


πŸ“Œ 문제

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

image

image


πŸ“Œ 풀이

와… 2번째둜 λ„μ „ν•˜λŠ” κ³¨λ“œ4 λ¬Έμ œμ™€ λ™μ‹œμ— 처음으둜 ν‘Ό κ³¨λ“œ 4 λ¬Έμ œμ΄λ‹€.
λ°₯λ¨ΉλŠ” μ‹œκ°„ μ œμ™Έν•˜κ³ , 8μ‹œκ°„μ€ κΌ¬λ°• 이 문제만 풀은 것 κ°™λ‹€.
κ·Έλ‚˜λ§ˆ μ‰½κ²Œ ν’€λ¦° μ΄μœ λŠ” λ©”λͺ¨λ¦¬ μ œν•œμ΄ λ„λ„ν•˜κ³ , 칸의 넓이가 50밖에 μ•ˆλ˜μ„œ 50^4 = 6250000μ΄λΌλŠ” o(n^4)κ°€ λ‚˜μ™€λ„ κ±±μ •μ—†λŠ” λ¬Έμ œλΌμ„œ λ©”λͺ¨λ¦¬ κ±±μ •μ•ˆν•˜κ³  ν’€μ–΄μ„œ μ‰½κ²Œ ν•΄κ²°λœ λ¬Έμ œμΈκ²ƒ κ°™λ‹€.

μ²˜μŒμ—λŠ” N x N크기의 posλΌλŠ” 클래슀λ₯Ό 인자둜 κ°€μ§€λŠ” 2차원 배열을 μ‚¬μš©ν•˜μ—¬ ꡬ상을 ν•˜μ˜€λ‹€.
νŒŒμ΄μ–΄λ³Όμ΄λΌλŠ” 객체λ₯Ό μ—¬λŸ¬κ°œ κ΅¬ν˜„ν•˜λŠ” ν˜•μ‹μ΄ μ•„λ‹Œ, 각 μ£Όμ†Œκ°’μ— ν˜„μž¬ νŒŒμ΄μ–΄λ³Όμ˜ 정보λ₯Ό μ €μž₯μ‹œν‚€λŠ” λ°©μ‹μœΌλ‘œ ꡬ상을 ν•˜μ˜€λ‹€.
이쀑 for문을 μ‚¬μš©ν•˜μ—¬, BFS처럼 첫칸뢀터 λ§ˆμ§€λ§‰ μΉΈκΉŒμ§€ μˆœμ„œλŒ€λ‘œ μ΄λ™μ‹œν‚€λŠ” μ‹μœΌλ‘œ κ΅¬ν˜„μ„ ν•˜λ €κ³  ν•˜μ˜€λ‹€.
이λ₯Ό μœ„ν•˜μ—¬ 속도 * DR[i] + ν˜„μž¬μœ„μΉ˜λ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μŒ 칸의 μœ„μΉ˜λ₯Ό κ΅¬ν•˜λ €κ³  ν–ˆλŠ”λ°, 이 μœ„μΉ˜κ°€ N보닀 μž‘μ„μˆ˜λ„, ν΄μˆ˜λ„ μžˆλ‹€λŠ” 문제점이 μžˆμ—ˆλ‹€.
이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•˜μ—¬, cur[0] + ((ODR[j] * curs+ N) % N처럼 μΌλΆ€λŸ¬ N을 λ”ν•΄μ„œ μ–‘μˆ˜λ‘œ λ§Œλ“€κ³  N으둜 λ‚˜λˆ μ„œ 인덱슀 문제λ₯Ό ν•΄κ²°ν•˜λ €κ³  ν•˜μ˜€λ‹€.
ν•˜μ§€λ§Œ λ§Œλ“€κ³ λ³΄λ‹ˆ 속도가 λ„ˆλ¬΄μ»€μ„œ N을 더해쀀값보닀 더 클 μˆ˜λ„ μžˆλ‹€λŠ” 생각이 λ“€μ—ˆλ‹€.
κ·Έλž˜μ„œ 속도λ₯Ό N으둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€μ— N값을 더해주고 λ‹€μ‹œ %N연산을 ν•΄μ£ΌλŠ” 살짝은 번거둜운 λ‹€μŒκ³Ό 같은 연산을 μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•˜μ˜€λ‹€.

(cur[0] + ((ODR[j] * curs) % N + N)) % N

이후 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ‹€κ°€ visited 배열을 μ‚¬μš©ν•˜λ”λΌλ„ 해결이 μ•ˆλ˜λŠ” λ¬Έμ œκ°€ ν•˜λ‚˜ μžˆμ—ˆλŠ”λ° λ°”λ‘œ, νŒŒμ΄μ–΄λ³Όμ΄ λ‹€μŒκ³Ό 같이 νŒŒμ΄μ–΄λ³Ό1이 [2,2]의 μœ„μΉ˜λ‘œ μ΄λ™ν•˜λ €κ³  ν• λ–„ ν•˜ν•„ κ·Έμžλ¦¬μ— λ‹€λ₯Έ νŒŒμ΄μ–΄λ³Όμ΄ 있으면, νŒŒμ΄μ–΄λ³Ό1은 λ‘λ²ˆ μ΄λ™ν•˜κ²Œ 되게 λœλ‹€.

image

이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•˜μ—¬ νŒŒμ΄μ–΄λ³Ό1이 μ΄λ™ν•œ ν›„, [2,2]의 자리λ₯Ό visited 배열에 λ„£μ–΄μ„œ, 검사λ₯Ό μ•ˆν•˜λ©΄ νŒŒμ΄μ–΄λ³Ό2λŠ” 움직이지 μ•Šκ²Œ λœλ‹€.

이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•˜μ—¬ κ²°κ΅­ λ‹€μŒμƒνƒœμ™€ ν˜„μž¬μƒνƒœλ₯Ό ꡬ별해야 λœλ‹€λŠ” 것을 느끼고, μ½”λ“œλ₯Ό μ²˜μŒλΆ€ν„° λ‹€μ‹œ 짜기 μ‹œμž‘ν–ˆλ‹€.
λ©”λͺ¨λ¦¬μ–‘이 λ„‰λ„‰ν•˜λ‹€λŠ” 것을 μ΄μš©ν•΄ κ·Έλƒ₯ currentfield 와 field λ₯Ό λ§Œλ“€μ–΄μ„œ ν˜„μž¬ μƒνƒœμ™€ λ‹€μŒ μƒνƒœλ₯Ό κ΅¬λ³„ν•˜μ˜€λ‹€.
그리고, ν­λ°œμ„ μ–΄λ–»κ²Œ κ΅¬ν˜„ν•΄μ•Ό ν•˜λ‚˜ μˆœμ„œλ₯Ό κ³ λ―Όν•˜λ‹€κ°€, 항상 폭발 -> 이동 λ°©μ‹μœΌλ‘œ isExplodeλΌλŠ” λ³€μˆ˜λ₯Ό μΆ”κ°€ν•˜μ—¬, μ΄λ™ν•˜κΈ°μ „μ— isExplodeκ°€ 거짓이면 κ·ΈλŒ€λ‘œ, 참이면 각각 EDR, ECR, ODR, OCRμ΄λΌλŠ” μƒμˆ˜ 인트 배열을 λ§Œλ“€μ–΄μ„œ dir % 8 값이 짝수면 μ•žμ˜ λ‘κ°œ, ν™€μˆ˜λ©΄ 뒀에 λ‘κ°œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν­λ°œμ„ κ΅¬ν˜„ν•˜μ˜€λ‹€.
ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ ν¬λ‚˜ν° μ˜€μ°¨κ°€ ν•˜λ‚˜ μƒκΈ°λŠ”λ° λ’€μ—μ„œ μ„€λͺ…ν•˜κ² λ‹€.

이후, ν•©μΉ˜λŠ” 것을 계속 κ΅¬ν˜„ν•˜λ‹€κ°€ 속도 λΆ€λΆ„μ—μ„œ λ¬Έμ œκ°€ 생겼닀.
μ›λž˜ κΈ°μ‘΄ λ“€μ–΄μ˜¨ 값에 μƒˆκ°’μ„ λ”ν•΄μ„œ 2λ₯Ό λ‚˜λˆ„λŠ” μ‹μœΌλ‘œ κ΅¬ν˜„μ„ ν•˜λ €λ‹€κ°€, μžμ„Ένžˆ 계산을 ν•΄λ³΄λ‹ˆ, countλΌλŠ” λ³€μˆ˜κ°’μ΄ 무쑰건 ν•„μš”ν•˜λ‹€λŠ” 것을 μ•Œκ²Œλ˜μ—ˆλ‹€.
κ·Έλž˜μ„œ λ’€λŠ¦κ²Œ pos에 λ„£μ–΄μ£Όμ—ˆλ‹€.

ν•˜μ§€λ§Œ 이 λͺ¨λ“  였λ₯˜λ₯Ό 고치고 λ‚˜μ„œλ„ 계속 1%μ—μ„œ ν‹€λ¦¬λŠ” 상황이 λ°˜λ³΅λ˜μ—ˆλ‹€.
λ„ˆλ¬΄λ‚˜λ„ ν™”κ°€λ‚¬μ§€λ§Œ μ°¨λΆ„ν•˜κ²Œ 디버깅을 μ°μœΌλ©΄μ„œ ν•œκ°€μ§€ λ¬Έμ œμ μ„ μ•Œκ²Œ λ˜μ—ˆλ‹€.
λ¬Έμ œμ—μ„œ λͺ¨λ‘ μ§μˆ˜μ΄κ±°λ‚˜, ν™€μˆ˜μΌλ•Œ μ‘°κ±΄μ—μ„œ 짝 + 짝 % 2 == 홀 + 홀 % 2 == 0 의 κ°œλ…μœΌλ‘œ 접근을 ν–ˆλŠ”λ°, 짝 짝 홀 홀 κ°™μ€κ²½μš° μ²˜λ¦¬κ°€ μ œλŒ€λ‘œ λ˜μ§€ μ•ŠλŠ” κ²ƒμ΄μ˜€λ‹€.
λ’€λŠ¦κ²Œ 이 사싀을 κΉ¨λ‹«κ³  고치기 μœ„ν•΄μ„œ isSameμ΄λΌλŠ” λ³€μˆ˜λ₯Ό λ„£κ³  final μƒμˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 이것을 class λ‚΄λΆ€μ—μ„œ ꡬ별을 ν•˜κ²Œ κ΅¬ν˜„ν•˜μ˜€λ‹€.

λ„ˆλ¬΄ μ–΄λ €μ› κ³ , μ‹œκ°„μ΄ μ˜€λž˜κ±Έλ Έμ§€λ§Œ, ν’€μ–΄λ‚΄λ‹ˆκΉŒ ν–‰λ³΅ν–ˆλ‹€. 😎


πŸ“Œ Code

package BOJ.Implements;

import java.io.*;
import java.util.*;

public class N20056 {
    static class pos {
        int m;
        int s;
        int d;
        boolean isExplode;
        int count;
        int isSame;

        public pos(int m, int s, int d, int count, int isSame, boolean isExplode) {
            this.m = m;
            this.s = s;
            this.d = d;
            this.count = count;
            this.isSame = isSame;
            this.isExplode = isExplode;
        }

        public boolean BigBang(int m, int s, int d) {
            if (this.m != 0) {
                this.isExplode = true;
                this.count += 1;
                if (this.isSame == notSame) {
                    this.isSame = notSame;
                } else if ((this.isSame == empty) || (this.isSame == d % 2)) {
                    this.isSame = d % 2;
                } else {
                    this.isSame = notSame;
                }
            } else {
                this.isSame = d % 2;
                this.isExplode = false;
                this.count = 1;
            }
            this.m += m;
            this.s += s;
            this.d += d;
            this.d %= 8;
            return isExplode;
        }

        public void reset() {
            this.m = 0;
            this.s = 0;
            this.d = 0;
            this.count = 0;
            this.isSame = empty;
            this.isExplode = false;
        }
    }


    static pos[][] field;
    static pos[][] curfield;
    static Queue<Integer[]> fire;
    static int N;
    static int M;
    static int K;
    static int empty = -1;
    static int notSame = -2;
    static final int[] DR = {-1, -1, 0, 1, 1, 1, 0, -1};
    static final int[] DC = {0, 1, 1, 1, 0, -1, -1, -1};
    static final int[] EDR = {-1, 0, 1, 0};
    static final int[] EDC = {0, 1, 0, -1};
    static final int[] ODR = {-1, 1, 1, -1};
    static final int[] ODC = {1, 1, -1, -1};


    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());
        K = Integer.parseInt(st.nextToken());

        curfield = new pos[N][N];
        field = new pos[N][N];

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                field[i][j] = new pos(0, 0, 0, 1, empty, false);
                curfield[i][j] = new pos(0, 0, 0, 1, empty, false);
            }
        }
        fire = new LinkedList<>();
        int r;
        int c;
        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            r = Integer.parseInt(st.nextToken()) - 1;
            c = Integer.parseInt(st.nextToken()) - 1;
            field[r][c] = new pos(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), 1, empty, false);
            fire.add(new Integer[]{r, c});
        }
        TotalTime(K);
    }

    static void TotalTime(int time) {
        //ShowAll();
        for (int i = 0; i < time; i++) {
            MoveFire();
            //ShowAll();
        }
        Count();
    }

    static void MoveFire() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                curfield[i][j] = new pos(field[i][j].m, field[i][j].s, field[i][j].d, field[i][j].count, field[i][j].isSame, field[i][j].isExplode);
                field[i][j].reset();
            }
        }
        int count = fire.size();
        int nextR;
        int nextC;
        int curm;
        int curs;
        int curd;
        Integer[] cur;
        for (int i = 0; i < count; i++) {
            cur = fire.poll();
            curm = curfield[cur[0]][cur[1]].m;
            curs = curfield[cur[0]][cur[1]].s;
            curd = curfield[cur[0]][cur[1]].d;
            if (curm <= 0) {
                continue;
            }
            if (!curfield[cur[0]][cur[1]].isExplode) {
                nextR = (cur[0] + ((DR[curd] * curs) % N + N)) % N;
                nextC = (cur[1] + ((DC[curd] * curs) % N + N)) % N;
                if (!field[nextR][nextC].BigBang(curm, curs, curd)) {
                    fire.add(new Integer[]{nextR, nextC});
                }
            } else {
                curm /= 5;
                curs /= curfield[cur[0]][cur[1]].count;
                if (curm <= 0) {
                    continue;
                }
                if (curfield[cur[0]][cur[1]].isSame == notSame) {
                    for (int j = 0; j < ODC.length; j++) {
                        nextR = (cur[0] + ((ODR[j] * curs) % N + N)) % N;
                        nextC = (cur[1] + ((ODC[j] * curs) % N + N)) % N;
                        if (!field[nextR][nextC].BigBang(curm, curs, 2 * j + 1)) {
                            fire.add(new Integer[]{nextR, nextC});
                        }
                    }
                } else {
                    for (int j = 0; j < EDC.length; j++) {
                        nextR = (cur[0] + ((EDR[j] * curs) % N + N)) % N;
                        nextC = (cur[1] + ((EDC[j] * curs) % N + N)) % N;
                        if (!field[nextR][nextC].BigBang(curm, curs, 2 * j)) {
                            fire.add(new Integer[]{nextR, nextC});
                        }
                    }
                }
            }
        }
    }

    static void Count() {
        int result = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (field[i][j].isExplode) {
                    result += (field[i][j].m / 5) * 4;
                } else {
                    result += field[i][j].m;
                }
            }
        }
        System.out.println(result);
    }


    static void ShowAll() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (field[i][j].m == 0) {
                    System.out.print(". ");
                } else if (field[i][j].isExplode) {
                    System.out.print(field[i][j].m + ")");
                } else {
                    System.out.print(field[i][j].m + " ");
                }
            }
            System.out.println();
        }
        System.out.println("==========================");
    }
}

package (이름); λ₯Ό λ•Œκ³ , class 이름을 Main으둜 λ³€κ²½ν•˜λ©΄ λœλ‹€.


πŸ“Œ μΆ”κ°€ 예제

[Input]
7 4 5
1 1 1 1 3
1 3 2 1 5
3 1 3 1 1
3 3 4 1 7

[Output]
8
[Input]
7 4 5
1 2 1 1 4
2 3 2 1 6
3 1 3 1 1
3 3 4 1 7

[Output]
8
[Input]
7 1 10
4 4 7 1 7

[Output]
7
[Input]
7 0 10

[Output]
0


개인 곡뢀 기둝용 λΈ”λ‘œκ·Έμž…λ‹ˆλ‹€.
ν‹€λ¦¬κ±°λ‚˜ 였λ₯˜κ°€ μžˆμ„ 경우 μ œλ³΄ν•΄μ£Όμ‹œλ©΄ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€.😁