1+ import java .io .*;
2+ import java .util .*;
3+
4+ public class Main {
5+ static int N ;
6+ static int [][] map ;
7+ static int sr , sc ; // shark row, col
8+ static int size = 2 ; // initial size
9+ static int eaten = 0 ; // eaten count toward next size
10+ static int time = 0 ; // total time (answer)
11+ static final int [] dr = {-1 , 0 , 0 , 1 }; // 상, 좌, 우, 하 (거리 동일시 행/열 우선 tie-break에 유리: 상→좌 우선 탐색)
12+ static final int [] dc = {0 , -1 , 1 , 0 };
13+
14+ public static void main (String [] args ) throws Exception {
15+ BufferedReader br = new BufferedReader (new InputStreamReader (System .in ));
16+ N = Integer .parseInt (br .readLine ().trim ());
17+ map = new int [N ][N ];
18+
19+ for (int i = 0 ; i < N ; i ++) {
20+ StringTokenizer st = new StringTokenizer (br .readLine ());
21+ for (int j = 0 ; j < N ; j ++) {
22+ map [i ][j ] = Integer .parseInt (st .nextToken ());
23+ if (map [i ][j ] == 9 ) { // 아기 상어 시작점
24+ sr = i ; sc = j ;
25+ map [i ][j ] = 0 ; // 빈 칸으로 바꿔둔다
26+ }
27+ }
28+ }
29+
30+ while (true ) {
31+ Target t = bfsFindTarget ();
32+ if (t == null ) break ; // 더 이상 먹을 물고기 없음
33+
34+ // 이동 & 섭취
35+ time += t .dist ;
36+ sr = t .r ; sc = t .c ;
37+ map [sr ][sc ] = 0 ;
38+ eaten ++;
39+ if (eaten == size ) {
40+ size ++;
41+ eaten = 0 ;
42+ }
43+ }
44+
45+ System .out .println (time );
46+ }
47+
48+ // 가장 가까운 먹이 하나를 찾는다. 없다면 null
49+ static Target bfsFindTarget () {
50+ int [][] dist = new int [N ][N ];
51+ for (int i = 0 ; i < N ; i ++) Arrays .fill (dist [i ], -1 );
52+
53+ ArrayDeque <int []> q = new ArrayDeque <>();
54+ q .add (new int []{sr , sc });
55+ dist [sr ][sc ] = 0 ;
56+
57+ int bestDist = Integer .MAX_VALUE ;
58+ int bestR = -1 , bestC = -1 ;
59+
60+ while (!q .isEmpty ()) {
61+ int [] cur = q .poll ();
62+ int r = cur [0 ], c = cur [1 ];
63+
64+ int d = dist [r ][c ];
65+ // 이미 발견한 최단 먹이 거리보다 멀면 더 볼 필요 없음
66+ if (d > bestDist ) continue ;
67+
68+ // 먹을 수 있는 물고기(1~6)이고, 상어 크기보다 작아야 함
69+ if (map [r ][c ] > 0 && map [r ][c ] < size ) {
70+ // 후보 갱신: 거리 최소, 거리 같으면 행 최소, 그래도 같으면 열 최소
71+ if (d < bestDist ||
72+ (d == bestDist && (r < bestR ||
73+ (r == bestR && c < bestC )))) {
74+ bestDist = d ;
75+ bestR = r ; bestC = c ;
76+ }
77+ // 같은 거리의 다른 후보가 있을 수 있으므로 계속 탐색하되,
78+ // 거리가 더 커지는 레벨은 위의 if (d > bestDist) 에 걸려 스킵됨.
79+ }
80+
81+ // 인접 칸으로 BFS 확장
82+ for (int k = 0 ; k < 4 ; k ++) {
83+ int nr = r + dr [k ];
84+ int nc = c + dc [k ];
85+ if (nr < 0 || nr >= N || nc < 0 || nc >= N ) continue ;
86+ if (dist [nr ][nc ] != -1 ) continue ;
87+ // 이동 가능 조건: 상어 크기보다 작거나 같은 칸만 통과 가능(0=빈칸 포함)
88+ if (map [nr ][nc ] <= size ) {
89+ dist [nr ][nc ] = d + 1 ;
90+ q .add (new int []{nr , nc });
91+ }
92+ }
93+ }
94+
95+ if (bestR == -1 ) return null ; // 못 찾음
96+ return new Target (bestR , bestC , bestDist );
97+ }
98+
99+ static class Target {
100+ int r , c , dist ;
101+ Target (int r , int c , int dist ) {
102+ this .r = r ; this .c = c ; this .dist = dist ;
103+ }
104+ }
105+ }
0 commit comments