PS/Implementation

백준 21611번: 마법사 상어와 블리자드 (Java)

닻과매 2022. 7. 23. 13:43

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

 

21611번: 마법사 상어와 블리자드

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그, 비바라기 마법을 할 수 있다. 오늘 새로 배운 마법은 블리자드이고, 크기가 N×N인 격자에서 연습하려고 한다. N은 항상 홀수이고, (

www.acmicpc.net

 

 

 

 

 

 

 

 


 

풀이

길이 구부정하게 있으므로 큐로 구현하면 각 method 구현이 간단합니다(머리를 싸매지 않아도 됩니다.). 다만, 속도도 빠를 줄 알았는데 그렇진 않네요. 다른 코드를 보니, 1차원 배열로 구현한게 더 빠릅니다.

제 풀이가 꽤 유니크한 편일 겁니다..ㅎㅎ

 

 

코드

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import java.io.*;
import java.util.*;
 
public class Main {
 
    static int[] dr = { 0-1100 };
    static int[] dc = { 000-11 };
    static int[][] map;
    static int N;
    static Queue<Integer> pebbles = new ArrayDeque<>();
    static int ans = 0;
    
    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());
        int M = Integer.parseInt(st.nextToken());
        map = new int[N+1][N+1];
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        
        init();
        int x = 0;
        while (x++ < M)    {
            st = new StringTokenizer(br.readLine());
            int d = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            blizzard(d, s);
            while (true) {
                if (!pop()) break;
            }
            copy();
        }
        System.out.println(ans);
    }
    
    static void init() {
        for (int i = 1; i < N*N; i++) {
            int[] cur = loc(i);
            int r = cur[0], c = cur[1];
            if (map[r][c] == 0continue;
            pebbles.offer(map[r][c]);
        }
    }
    
    static void blizzard(int d, int s) {
        Set<Integer> destroy = new HashSet<>();
        int mid = (N+1)/2;
        int r = mid, c = mid;
        for (int i = 0; i < s; i++) {
            r += dr[d];
            c += dc[d];
            destroy.add(idx(r, c));
        }
        
        Queue<Integer> nextPebbles = new ArrayDeque<>();
        int idx = 1;
        while (!pebbles.isEmpty()) {
            if (destroy.contains(idx)) pebbles.poll();
            else nextPebbles.offer(pebbles.poll());
            idx++;
        }
        pebbles = nextPebbles;
    }
    
    static boolean pop() {
        boolean flag = false;
        Queue<Integer> tempPebbles = new ArrayDeque<>();
        Queue<Integer> nextPebbles = new ArrayDeque<>();
        while (!pebbles.isEmpty()) {
            if (tempPebbles.isEmpty()) tempPebbles.offer(pebbles.poll());
            else {
                if (tempPebbles.peek() == pebbles.peek()) {
                    tempPebbles.offer(pebbles.poll());
                } else {
                    if (tempPebbles.size() < 4) {
                        while (!tempPebbles.isEmpty()) {
                            nextPebbles.offer(tempPebbles.poll());
                        }
                        tempPebbles.offer(pebbles.poll());
                    } else {
                        ans += tempPebbles.peek() * tempPebbles.size();
                        tempPebbles.clear();
                        tempPebbles.offer(pebbles.poll());
                        flag = true;
                    }
                }
            }
        }
        if (tempPebbles.size() < 4) {
            while (!tempPebbles.isEmpty()) {
                nextPebbles.offer(tempPebbles.poll());
            }
        } else {
            ans += tempPebbles.peek() * tempPebbles.size();
            tempPebbles.clear();
            flag = true;
        }
        pebbles = nextPebbles;
        return flag;
    }
    
    static void copy() {
        Queue<Integer> tempPebbles = new ArrayDeque<>();
        Queue<Integer> nextPebbles = new ArrayDeque<>();
        while (!pebbles.isEmpty()) {
            if (tempPebbles.isEmpty()) tempPebbles.offer(pebbles.poll());
            else {
                if (tempPebbles.peek() == pebbles.peek()) {
                    tempPebbles.offer(pebbles.poll());
                } else {
                    nextPebbles.offer(tempPebbles.size());
                    nextPebbles.offer(tempPebbles.peek());
                    tempPebbles.clear();
                    tempPebbles.offer(pebbles.poll());
                }
            }
        }
        
        if (!tempPebbles.isEmpty()) {
            nextPebbles.offer(tempPebbles.size());
            nextPebbles.offer(tempPebbles.peek());
            tempPebbles.clear();
        }
        
        int cnt = 0;
        while (!nextPebbles.isEmpty() && cnt < N*N-1) {
            pebbles.offer(nextPebbles.poll());
            cnt++;
        }
        nextPebbles.clear();
    }
    
    // (r, c)의 위치를 찾는 method
    static int idx(int r, int c) {
        int m = (N+1)/2;
        int l = Math.max(Math.abs(r-m), Math.abs(c-m));
        int ret = (2*l-1)*(2*l-1- 1;
        if (c == m-&& r > m-l) ret += r - (m-l);
        else if (r == m+l) ret += 2*+ c - (m-l);
        else if (c == m+l) ret += 4*+ (m+l) - r;
        else ret += 6*+ (m+l) - c;
        return ret;
    }
    
    // i번째 구슬의 위치를 찾는 method
    static int[] loc(int idx) {
        int m = (N+1)/2;
        int l = (int) (Math.sqrt(idx)+1/ 2;
        idx -= (2*l-1)*(2*l-1-1;
        if (idx <= 2*l) return new int[] {m-l+idx, m-l};
        else if (idx <= 4*l) return new int[] {m+l, (idx-2*l) + (m-l)};
        else if (idx <= 6*l) return new int[] {(m+l)-(idx-4*l), m+l};
        else return new int[] {m-l, (m+l) - (idx-6*l)};
    }
}
 
cs