코테/백준

[백준/JAVA] 20056번: 마법사 상어와 파이어볼

imname1am 2024. 3. 23. 23:24
반응형

📖 문제

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

 

 

💡  풀이 방식

• 구현, 시뮬레이션

필요 자료구조
- 파이어볼 이동 시 정보 (2차원 ArrayList 배열 !!)
- 모든 파이어볼 정보 저장할 ArrayList

 

1. 파이어볼 정보 저장용 리스트에 파이어볼 정보를 저장한다.

2. K번 이동시키고, 파이어볼을 분열시킨다.

   2-1) [파이어볼 이동] 반복문을 통해 리스트에 있는 파이어볼들의 위치를 이동시키고, 파이어볼 이동 시 정보를 나타내는 2차원 리스트 배열 map의 새 위치에 현재 객체를 저장한다.

 

   2-2) [파이어볼 분열] 2차원 for문을 통해 모든 좌표를 돌며 파이어볼 갯수가 2개 미만인 경우, map[i][j]에 있는 원소를 모두 제거한다. / 파이어볼 갯수가 2개 이상인 경우, 분열을 진행한다.

 

3. 리스트에 있는 파이어볼들의 질량의 합을 구한다.

 

 

 

 

💥 유의사항

 

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import java.util.*;
import java.io.*;
 
public class Main {
    static int[] dx = {-1-101110-1};
    static int[] dy = {01110-1-1-1};
    
    static int N,M,K;
    static List<Fireball>[][] map;  // 파이어볼 이동 시 정보 (⭐ 2차원 리스트 배열!!)
    static List<Fireball> list = new ArrayList<>(); // 모든 파이어볼 정보
    
    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());
        
        map = new ArrayList[N][N];  // 2차원 ArrayList 배열!!
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < N ; j++)
                map[i][j] = new ArrayList<>();
        }
        
        while(M --> 0) {
            st = new StringTokenizer(br.readLine(), " ");
            int r = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            
            list.add(new Fireball(r-1,c-1,m,s,d));
        }
        
        while(K --> 0) {
            move();
            fire();
        }
        
        int answer = 0;
        for(Fireball fb : list)
            answer += fb.m;
        
        System.out.println(answer);
    }
    
    // 1. 파이어볼 이동 메서드
    private static void move() {
        for(Fireball fb : list) {
            int nx = (fb.r + dx[fb.d] * (fb.s%N) + N) % N;
            int ny = (fb.c + dy[fb.d] * (fb.s%N) + N) % N;
            
            fb.r = nx;
            fb.c = ny;
            
            map[fb.r][fb.c].add(fb);
        }
    }
    
    // 2. 파이어볼 분열 메서드
    private static void fire() {
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < N ; j++) {
                // 파이어볼 갯수가 2개 미만인 경우
                if(map[i][j].size() < 2) { 
                    map[i][j].clear();
                    continue;
                }
                
                // 파이어볼 갯수가 2개 이상인 경우
                int mSum = 0, sSum = 0;
                int oddCnt = 0, evenCnt = 0;
                int size = map[i][j].size();
                
                // 분열 진행
                for(Fireball fb : map[i][j]) {
                    mSum += fb.m;
                    sSum += fb.s;
                    
                    if(fb.d % 2 == 1)   oddCnt++;
                    else                evenCnt++;
                    
                    list.remove(fb);    // 💥 분열된 파이어볼 제거
                }
                map[i][j].clear();
                
                mSum /= 5;  // 분열된 질량 구하기
                if(mSum == 0)   continue; // 질량이 0인 파이어볼은 소멸되어 없어짐
                
                sSum /= size;   // 분열된 속도 구하기
                
                // 모든 파이어볼 방향이 짝수이거나 홀수인 경우
                if(oddCnt == size || evenCnt == size) {
                    for(int x = 0 ; x < 8 ; x += 2// 0,2,4,6 방향 분열
                        list.add(new Fireball(i, j, mSum, sSum, x));
                }
                else {
                    for(int x = 1 ; x < 8 ; x += 2// 1,3,5,7 방향 분열
                        list.add(new Fireball(i, j, mSum, sSum, x));
                }
            }
        }
    }
}
 
class Fireball {
    int r, c, m, s, d;
    
    public Fireball(int r, int c, int m, int s, int d) {
        this.r = r;
        this.c = c;
        this.m = m;
        this.s = s;
        this.d = d;
    }
}
 
cs

 

 

 

➕ 다른 풀이 방식

3차원 map과 큐를 활용하신 풀이

 

[백준] 20056 - 마법사 상어와 파이어볼 (JAVA)

소요시간 : 1시간 5분문제 사이트 : 백준문제 수준 : 골드 4문제 유형 : 구현, 시뮬레이션다른 사람의 풀이를 참고 했는가 ? : X문제 링크 : https://www.acmicpc.net/problem/20056푼 날짜 : 2023.05.04구현, 시뮬

velog.io

 


💦 어려웠던 점

- 2차원 배열 좌표 리스트로 값을 저장하고 싶은데 어떻게 해야하지?의 문제..

 

🧐 새로 알게 된 내용

- List<Fireball>[][] map : 2차원 ArrayList 배열...

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

 

[백준] 알고리즘 분류(구현,JAVA)20056번, 마법사 상어와 파이어볼

문제 링크 20056번: 마법사 상어와 파이어볼 첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이

tussle.tistory.com

 

반응형