Skip to content

Commit 4ae9915

Browse files
authored
Merge pull request #2036 from AlgorithmWithGod/LiiNi-coder
[20260321] BOJ / G3 / 아기상어 / 이인희
2 parents 0ab9881 + 5adf90f commit 4ae9915

1 file changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
```java
2+
import java.io.BufferedReader;
3+
import java.io.IOException;
4+
import java.io.InputStreamReader;
5+
import java.util.ArrayDeque;
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.Collections;
9+
import java.util.Deque;
10+
import java.util.HashSet;
11+
import java.util.List;
12+
import java.util.StringTokenizer;
13+
14+
public class Main{
15+
/*
16+
* 물고기 m마리, 아기상어
17+
* 아기상어 처음 크기 2
18+
* 1초에 상하좌우 한칸 이동 / 동시에 먹음 / 그칸은 빈칸이 됨 / 아기상어 크기만큼 물고기 먹으면 크기가 증가
19+
* 자신보다 큰 물고가칸 못감 / 나머진 가능
20+
* 자신보다 작은 물고기는 먹을수있음
21+
* 아기상어 이동 루틴
22+
* 1. 더이상 먹을수있는 물고기가 없다면 끝
23+
* 2. 먹을수있는 물고기 == 1 : 거기로 감
24+
* 3. 먹을수있는 물고기 > 1: 가장 가까운 물고기
25+
* 3-1. 만약 가장 가까운 물고기가 많다면 가장위 -> 그것도 많다면 가장 왼쪽
26+
* */
27+
28+
/* 1. 아기상어 이동목표 선정 : O(N)
29+
1. 바로 해당 아기상어보다 같거나 작은 애들의 좌표를 알수있어야함
30+
2. 그중 가장 가까운 것을 바로 찾을수있어야함(절댓값구하면됨)
31+
3. 2번을 쌓아놓고 그중에서 가장 위, 왼쪽을 찾아야함
32+
* 아기상어의 크기는 도중에 바뀜 -> 1.1 변동됨
33+
*/
34+
static int N;
35+
static int Size = 2;
36+
static int[] Coords = new int[2];
37+
static List<List<int[]>> FishAtSize;
38+
static int[][] Drdcs = {
39+
{0, 1},
40+
{1, 0},
41+
{0, -1},
42+
{-1, 0}
43+
};
44+
static int[][] Map;
45+
public static void main(String[] args)throws IOException {
46+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
47+
/*
48+
0은 빈칸
49+
1, 2, 3, 4, 5, 6은 칸에 있는 물고기 크기
50+
9는 아기상어 위치
51+
*/
52+
N = Integer.parseInt(br.readLine());
53+
FishAtSize = new ArrayList<>();
54+
for(int i = 0; i < 7; i++){
55+
FishAtSize.add(new ArrayList<>());
56+
}
57+
Map = new int[N][N];
58+
for(int r = 0; r<N; r++){
59+
StringTokenizer st = new StringTokenizer(br.readLine());
60+
for(int c = 0; c<N; c++){
61+
int value = Integer.parseInt(st.nextToken());
62+
if(value == 0) continue;
63+
else if(value == 9) {
64+
Coords[0] = r;
65+
Coords[1] = c;
66+
}else if(value >= 1 && value <= 6){
67+
FishAtSize.get(value).add(new int[]{r, c});
68+
Map[r][c] = value;
69+
}
70+
}
71+
}
72+
73+
int t = 0;
74+
int countEating = Size;
75+
HashSet<Integer> blackList = new HashSet<>();
76+
while(true) {
77+
List<int[]> q1 = new ArrayList<>();
78+
List<int[]> q2 = new ArrayList<>();
79+
80+
81+
82+
// // 2. 큐1중에서 가장 가까운 애들 큐2에 넣음
83+
// int i = 0;
84+
// int[] dists = new int[q1.size()];
85+
// int minDist = Integer.MAX_VALUE;
86+
// for (int[] fishCoord : q1) {
87+
// // 2-1.q1에서 i번째마다 거리를 모두 구함
88+
// dists[i] = Math.abs(fishCoord[0] - Coords[0]) + Math.abs(fishCoord[1] - Coords[1]);
89+
// minDist = Math.min(minDist, dists[i]);
90+
// i++;
91+
// }
92+
// //2-1. 굳이정렬? 그냥 가장 최솟값을 가지는 애들을 q2에 넣음
93+
// i = 0;
94+
// for (int[] fishCoord : q1) {
95+
// if (dists[i] == minDist)
96+
// q2.add(fishCoord);
97+
// i++;
98+
// }
99+
100+
// 2. fish1DSet을 발견할때 bfs로 하여서 가장 작은 값을 구하고
101+
Deque<int[]> qbfs = new ArrayDeque<>();
102+
qbfs.add(new int[]{Coords[0], Coords[1], 0});
103+
int minDist = Integer.MAX_VALUE;
104+
boolean validMinDist = false;
105+
boolean[][] visited = new boolean[N][N];
106+
visited[Coords[0]][Coords[1]] = true;
107+
while(!qbfs.isEmpty()){
108+
int[] qItem = qbfs.poll();
109+
int r = qItem[0]; int c = qItem[1]; int step = qItem[2];
110+
if(validMinDist && minDist <= step)
111+
continue;
112+
for(int[] drdc: Drdcs){
113+
int nr = r + drdc[0];
114+
int nc = c + drdc[1];
115+
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
116+
if(visited[nr][nc]) continue;
117+
if(Map[nr][nc] > Size) continue;
118+
// 자신보다 작은 것들만 먹을수있으
119+
if(Map[nr][nc] < Size && Map[nr][nc] >= 1){
120+
if(blackList.contains(N*nr + nc)) continue;
121+
if(!validMinDist){
122+
validMinDist = true;
123+
minDist = step+1;
124+
}
125+
q2.add(new int[]{nr, nc});
126+
}
127+
qbfs.add(new int[]{nr, nc, step+1});
128+
visited[nr][nc] = true;
129+
}
130+
}
131+
132+
133+
// printArr(q2);
134+
135+
// 3. 큐2중에서 가장 위 -> 가장 왼쪽애를 targetCoords에 넣음
136+
// 이쯤되면 그냥 정렬해도되지않을까(채에 2번 걸렀으니)
137+
Collections.sort(q2, (o1, o2) -> {
138+
if (o1[0] == o2[0]) {
139+
return o1[1] - o2[1];
140+
}
141+
return o1[0] - o2[0];
142+
});
143+
int[] targetCoord = q2.isEmpty()? null: q2.get(0);
144+
if (targetCoord == null) {
145+
break;
146+
}
147+
148+
//System.out.println("targetCoord : (%d, %d)".formatted(targetCoord[0], targetCoord[1]));
149+
150+
//Coords 이동
151+
Coords[0] = targetCoord[0];
152+
Coords[1] = targetCoord[1];
153+
// 시간 더하기
154+
t += minDist;
155+
// 아기상어 크기 처리
156+
countEating--;
157+
if(countEating <= 0 ){
158+
Size++;
159+
countEating = Size;
160+
}
161+
// 해당 칸에 속한 물고기 삭제
162+
blackList.add(N*targetCoord[0] + targetCoord[1]);
163+
Map[targetCoord[0]][targetCoord[1]] = 0;
164+
//System.out.println("Coord: " + Arrays.toString(Coords));
165+
// System.out.println("t, size : " + t + ", " + Size);
166+
}
167+
System.out.println(t);
168+
br.close();
169+
}
170+
171+
static void printArr(List<int[]> arrs){
172+
StringBuilder sb = new StringBuilder();
173+
for(int[] arr: arrs)
174+
sb.append("(").append(arr[0]).append(", ").append(arr[1]).append("\n");
175+
System.out.println(sb.toString());
176+
}
177+
}
178+
```

0 commit comments

Comments
 (0)