[백준/BOJ] 20057 마법사 상어와 토네이도 - JAVA

2025. 6. 17. 17:17·알고리즘/문제풀이

[백준/BOJ] 20057 마법사 상어와 토네이도 - JAVA

문제

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

 

문제 분석

조건

N x N 격자의 중앙에서 시작한 토네이도가 바깥으로 나선형으로 이동한다. 토네이도가 특정 칸으로 이동하면, 그 칸의 모든 모래가 일정한 비율에 따라 주변 칸으로 흩어진다. 이때 격자 밖으로 나간 모래의 총 양을 구하는 것이 문제의 목표이다.

풀이방법

토네이도 클래스를 정의하여 토네이도의 위치, 방향, 상태와 이동을 다루는 변수와 함수를 작성했다.

모래가 날리는 부분은 `SPREAD_PATTERN`을 3차원 배열을 통해 미리 모두 정의해두었다. 현재 방향에 맞는 패턴을 조회하여 바로 사용하도록 했다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static class Tornado {
        int r, c, dir;
        int moveLength; // 지금 방향으로 이동할 수 있는 거
        int moveCount;  // 지금 방향으로 이동한 거리
        int dirChangeCount; // 방향 바꾼 횟수

        public Tornado(int startPos) {
            this.r = startPos;
            this.c = startPos;
            this.dir = 0;
            this.moveLength = 1;
            this.moveCount = 0;
            this.dirChangeCount = 0;
        }

        public void changeDir() {
            this.dir = (this.dir + 1) % 4;
            moveCount = 0;
            dirChangeCount++;
            if (dirChangeCount == 2) {  // 방향을 2번 바꿀때마다 이동 거리가 증가
                moveLength++;
                dirChangeCount = 0;
            }
        }

        public void move() {
            this.r += dirs[dir][0];
            this.c += dirs[dir][1];
            this.moveCount++;
        }

        public boolean alive() {
            return this.r != 0 || this.c != 0;
        }

        public boolean isTurn() {   // 이동할 수 있는 거리만큼 이동하면 회전
            return moveCount == moveLength;
        }
    }

    static int[][] dirs = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
    static int[][][] SPREAD_PATTERN = { // 방향에 따른 모래 이동 좌표와 퍼센트 [r, c, 퍼센트]
            {{0, -2, 5}, {-1, -1, 10}, {1, -1, 10}, {-1, 0, 7}, {1, 0, 7}, {-2, 0, 2}, {2, 0, 2}, {-1, 1, 1}, {1, 1, 1}},
            {{2, 0, 5}, {1, -1, 10}, {1, 1, 10}, {0, -1, 7}, {0, 1, 7}, {0, -2, 2}, {0, 2, 2}, {-1, 1, 1}, {-1, -1, 1}},
            {{0, 2, 5}, {-1, 1, 10}, {1, 1, 10}, {-1, 0, 7}, {1, 0, 7}, {-2, 0, 2}, {2, 0, 2}, {-1, -1, 1}, {1, -1, 1}},
            {{-2, 0, 5}, {-1, -1, 10}, {-1, 1, 10}, {0, -1, 7}, {0, 1, 7}, {0, -2, 2}, {0, 2, 2}, {1, 1, 1}, {1, -1, 1}}
    };
    static int[][] map;
    static int N, answer;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        N = Integer.parseInt(br.readLine());
        map = new int[N][N];
        for (int r = 0; r < N; r++) {
            st = new StringTokenizer(br.readLine());
            for (int c = 0; c < N; c++) {
                map[r][c] = Integer.parseInt(st.nextToken());
            }
        }
        Tornado tornado = new Tornado(N / 2);

        while (tornado.alive()) {
            tornado.move();
            sand(tornado.r, tornado.c, tornado.dir);
            if (tornado.isTurn()) {
                tornado.changeDir();
            }
        }
        System.out.println(answer);
    }

    // 모래 날리기
    private static void sand(int r, int c, int dir) {
        int total = map[r][c];
        int remain = total;
        map[r][c] = 0;

        for (int[] pattern : SPREAD_PATTERN[dir]) {
            int nextR = r + pattern[0];
            int nextC = c + pattern[1];
            int sand = (total * pattern[2]) / 100;
            if (isValid(nextR, nextC)) {
                map[nextR][nextC] += sand;
            } else {
                answer += sand;
            }
            remain -= sand;
        }

        int nextR = r + dirs[dir][0];
        int nextC = c + dirs[dir][1];
        if (isValid(nextR, nextC)) {
            map[nextR][nextC] += remain;
        } else {
            answer += remain;
        }
    }

    private static boolean isValid(int nextR, int nextC) {
        return !(nextR < 0 || nextC < 0 || nextR >= N || nextC >= N);
    }
}

 

728x90
저작자표시 비영리 변경금지 (새창열림)
'알고리즘/문제풀이' 카테고리의 다른 글
  • [백준/BOJ] 2252 줄 세우기 - JAVA
  • [프로그래머스] 86053 금과 은 운반하기 - JAVA(파라메트릭 서치)
  • [백준/BOJ] 2146 다리 만들기 - JAVA
  • [백준/BOJ] 20056 마법사 상어와 파이어볼 - JAVA
LIRI
LIRI
  • LIRI
    기록
    LIRI
  • 전체
    오늘
    어제
    • 분류 전체보기 (74)
      • 블로그 꾸미기 (0)
      • Spring (6)
      • 바이브코딩 (1)
      • React (3)
      • CS (0)
      • 알고리즘 (57)
        • 개념 (2)
        • 문제풀이 (54)
      • Java (1)
      • DB (1)
      • log (4)
        • SSAFY (3)
        • 궁금 (1)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    BFS
    알고리즘
    너비우선탐색
    리액트
    커서ai
    알고리즘 문제풀이
    바이브코딩
    Spring
    LIS
    Java
    pccp모의고사
    비트마스킹
    SSAFY 9기
    JWT
    Security
    dfs
    lv3
    springboot
    ssafy 합격 후기
    싸피
    그리디
    최장증가부분수열
    프로그래머스
    BOJ
    느좋코딩
    LV2
    Springsecurity
    SSAFY
    dp
    백준
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
LIRI
[백준/BOJ] 20057 마법사 상어와 토네이도 - JAVA
상단으로

티스토리툴바