본문 바로가기
Algorithm/Baekjoon

[JAVA] BOJ20057 마법사 상어와 토네이도

by 드헤 2023. 12. 13.

알고리즘 분류

  • 구현
  • 시뮬레이션

 

문제 풀이 방법

  • 우선 토네이도가 이동하는 경로를 while문을 통해 작성한다.
  • 토네이도가 왼쪽으로 이동할 때를 기준으로 해서 모래가 확산될 수 있는 방향 벡터(scatterR, scatterC)를 정의한다.
  • 그리고 토네이도가 회전할 때마다 토네이도의 방향벡터의 변화를 확인하면서 모래가 확산될 수 있는 방향벡터도 같이 계산해준다.
  • 이번에도 벡터를 활용해서 문제풀이를 하였다. 설명이 부족할 수도 있지만, 내가 문제풀이를 할 때 생각했던 것들을 정리해보았다.
    (왜 이런지 이상하거나, 모르겠으면 질문 고고)

코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

/*
 * 마법사 상어와 토네이도
 */

public class Main {
    static class Point {
        int r, c;

        public Point(int r, int c) {
            this.r = r;
            this.c = c;
        }
    }
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int N, map[][];
    static long result;
    static int dr[] = {0, 1, 0, -1};
    static int dc[] = {-1, 0, 1, 0};
    static int scatterR[] = {0, -2, 2, 1, 1, 1, -1, -1, -1, 0};
    static int scatterC[] = {-2, 0, 0, -1, 0, 1, -1, 0, 1, -1};
    static double ratio[] = {5, 2, 2, 10, 7, 1, 10, 7, 1};

    public static void main(String[] args) throws Exception {
        N = Integer.parseInt(br.readLine());

        map = new int[N][N];

        for (int r = 0; r < map.length; r++) {
            st = new StringTokenizer(br.readLine());

            for (int c = 0; c < map[r].length; c++) {
                map[r][c] = Integer.parseInt(st.nextToken());
            }
        }

        Point point = new Point(N / 2, N / 2);

        int l = 0;
        int d = 0;

        L: while(true) {

            if(d == 0 || d == 2) l++;

            int count = 0;

            while(count < l) {
                if(point.r == 0 && point.c == 0) break L;
                int nr = point.r + dr[d];
                int nc = point.c + dc[d];

                func(point.r, point.c, d);

                point.r = nr;
                point.c = nc;

                count++;
            }

            d =  (d + 1) % 4;
        }

        System.out.println(result);
    }

    private static void func(int r, int c, int d) {
        int sum = 0;

        int dirR[] = new int[10];
        int dirC[] = new int[10];

        if(d == 0) {
            dirR = scatterR;
            dirC = scatterC;
        }
        if(d == 1) {
            for(int i = 0; i < 10; i++) {
                dirR[i] = -scatterC[i];
            }
            dirC = scatterR;
        }
        if(d == 2) {
            dirR = scatterR;
            for(int i = 0; i < 10; i++) {
                dirC[i] = -scatterC[i];
            }
        }
        if(d == 3) {
            dirR = scatterC;
            dirC = scatterR;
        }

        r += dr[d];
        c += dc[d];

        for(int i = 0; i < 9; i++) {
            int nr = r + dirR[i];
            int nc = c + dirC[i];

            int tmp = (int) (map[r][c] * ratio[i] / 100);
            sum += tmp;

            if(!check(nr, nc)) { 
                result += tmp;
                continue;
            }

            map[nr][nc] += tmp;
        }

        int nr = r + dr[d];
        int nc = c + dc[d];

        if(!check(nr, nc)) {
            result += (map[r][c] - sum);
        } else {
            map[nr][nc] = map[nr][nc] + map[r][c] - sum;
        }

        map[r][c] = 0;
    }

    private static boolean check(int nr, int nc) {
        return nr >= 0 && nr < N && nc >= 0 && nc < N;
    }
}

 

느낀점

  • 시뮬레이션 문제는 한 문제 안에서도 작은 것부터 시작하면서 결국 문제를 해결하는 과정이 재미있는 것 같다. 하지만 이번 문제에서는 수식을 정리하고 디버깅을 하는데 시간을 너무 많이 사용했다. 앞으로 문제풀이를 할 때 집중해서 짧은 시간에 정확하게 풀어보도록 하자!

'Algorithm > Baekjoon' 카테고리의 다른 글

[JAVA] BOJ1089 스타트링크 타워  (0) 2024.02.01
[JAVA] BOJ2293 동전 1  (0) 2024.01.15
[JAVA] BOJ1753 최단경로  (0) 2023.12.18
[JAVA] BOJ1915 가장 큰 정사각형  (0) 2023.12.13
[JAVA] BOJ15685 드래곤 커브  (0) 2023.12.13