Study Algorithm

백준_16236_아기상어

_리므_ 2020. 5. 4. 01:40

[로직 설명]

1. 먹을 것이 있는지 체크해준다. 있다면 True 없다면 False반환 (checkEat 메소드)

    1-1. 먹을 것이 없다면, 지금까지의 시간을 출력하고 끝낸다.

    1-2. 있다면, 2번으로

2. bfs를 통해 거리 탐색을 한다. 이 때, 아기상어의 크기와 같거나 작아야지만 지나칠 수 있다는 조건을 걸어준다.

3. 거리탐색은 크기나 작거나 같아도 지나갈 수 있지만, 먹을 수있는 것은 크기가 작아야만 한다. 따라서, 아기 상어보다 크기가 작은 것들을 찾고 그 중에서 가장 가까운 거리를 minTime 변수에 저장해준다.

4. 가장 가까운 거리들의 먹이가 여러개 있을 수 있으므로, minTime과 같은 거리의 좌표들을 찾아 ArrayList에 담아준다. (이 때, 먹이의 크기가 0이거나 아기상어의 크기와 같은것은 안된다.)

5. compareTo를 이용하여 arraylist를 정렬해준다.(맨 위에 있는 먹이가 가장 앞으로 그 다음 왼쪽에 있는 먹이가 앞으로 -문제 조건 참고)

6.  가장 가까운 곳에 있고 문제의 조건에 만족하는 것은 arraylist의 맨 앞에 올것이어서, 아기상어의 다음좌표(babyY, babyX)를 갱신한다. 

7. 하나의 먹이를 먹었으므로, grow값을 증가시키고, 이 grow의 값과 baby변수(아기상어크기) 값이 같아지면, baby를 1 증가시키며, grow값은 0으로 초기화한다.

8. 마지막으로 다시 먹을 것이 있는지 확인한 뒤, 먹을 것이 있다면 shark()메소드를 실행하여 전체 과정을 반복한다. 없다면, 함수를 종료시킨다.

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
162
163
164
 
public class Main {
    static int N, baby, babyY, babyX, time, grow;
    static int[][] map, cnt;
    static boolean[][] visited;
    static int[] dy = { -1010 };
    static int[] dx = { 0-101 };
 
    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());
        map = new int[N][N];
 
        babyY = 0;
        babyX = 0;
        for (int i = 0; i < map.length; i++) {
            st = new StringTokenizer(br.readLine());
            if (st.hasMoreTokens()) {
                for (int j = 0; j < map[i].length; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                    if (map[i][j] == 9) {
                        babyY = i;
                        babyX = j;
                    }
                }
            }
        }
        grow = 0;
        baby = 2;
        time = 0;
        shark();
    }
 
    public static void shark() {
        if (checkEat()) {
            bfs(babyY, babyX);
            int minTime = Integer.MAX_VALUE;
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (cnt[i][j] != 0 && map[i][j] != 0 && map[i][j] < baby) {
                        if (minTime > cnt[i][j]) {
                            minTime = cnt[i][j];
                        }
                    }
                }
            }
 
            ArrayList<Edge> al = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (cnt[i][j] == minTime && map[i][j] != 0 && map[i][j] != baby) {
                        al.add(new Edge(i, j));
                    }
                }
            }
            if (al.size() == 0) {
                System.out.println(time);
                return;
            }
            Collections.sort(al);
            time += minTime;
            babyY = al.get(0).y;
            babyX = al.get(0).x;
            grow++;
            map[babyY][babyX] = 0;
            if (grow == baby) {
                baby++;
                grow = 0;
            }
 
            if (checkEat()) {
                shark();
            } else {
                System.out.println(time);
                return;
            }
        } else {
            System.out.println(time);
            return;
        }
 
    }
 
    public static boolean checkEat() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (map[i][j] > 0 && map[i][j] <= baby) {
                    return true;
                }
            }
        }
        return false;
    }
 
    public static void bfs(int y, int x) {
        map[y][x] = 0;
        visited = new boolean[N][N];
        cnt = new int[N][N];
 
        Queue<int[]> que = new LinkedList<>();
        que.offer(new int[] { y, x });
        visited[y][x] = true;
 
        while (!que.isEmpty()) {
            int[] tmp = que.poll();
            int cy = tmp[0];
            int cx = tmp[1];
 
            for (int d = 0; d < 4; d++) {
                int ny = cy + dy[d];
                int nx = cx + dx[d];
 
                if (safe(ny, nx) && !visited[ny][nx] && map[ny][nx] <= baby) {
                    visited[ny][nx] = true;
                    cnt[ny][nx] = cnt[cy][cx] + 1;
                    que.offer(new int[] { ny, nx });
                }
            }
        }
    }
 
    public static class Edge implements Comparable<Edge> {
        int y;
        int x;
 
        public Edge(int y, int x) {
            this.y = y;
            this.x = x;
        }
 
        @Override
        public int compareTo(Edge o) {
            if (this.y > o.y) {
                return 1;
            } else if (this.y == o.y) {
                if (this.x < o.x) {
                    return 1;
                } else {
                    return 0;
                }
            } else {
                return -1;
            }
        }
    }
 
    public static boolean safe(int y, int x) {
        if (y < N && x < N && y >= 0 && x >= 0) {
            return true;
        }
        return false;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

 

처리해야 할 조건들이 많아 로직이 흔들릴 수 있지만 문제 설명대로 차근히 풀어나가면 어렵지 않은 문제인 것 같다.

필요한 스킬 : BFS, Comparable 인터페이스