본문 바로가기
알고리즘/백준

[JAVA]백준_16236_아기상어

by 박 현 황 2021. 3. 4.

문제링크

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

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

 

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {

	static int N; // 공간의 크기
	static int time = 0;
	static int sharkSize = 2; // 현재 아기 상어의 크기
	static int sharkUp = 0; // 상어 크기 만큼 먹었을 때 크기 UP 해주기
	static int map[][];
	static boolean isVisited[][];
	static int shark[]; // 아기 상어 위치 저장할 배열
	static ArrayList<Node> list = new ArrayList<>();
	static int dx[] = { 0, 0, -1, 1 };
	static int dy[] = { -1, 1, 0, 0 };
	static Queue<Node> q = new LinkedList<>();

	public static void main(String[] args) throws NumberFormatException, IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		StringTokenizer st;

		map = new int[N][N];
		isVisited = new boolean[N][N];
		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
				if (map[i][j] == 9)
					shark = new int[] { i, j }; // 아기상어 위치 입력
				if (map[i][j] >= 1 && map[i][j] <= 6)
					list.add(new Node(i, j, map[i][j])); // 물고기들 위치와 size setting

			}
		} // 배열 입력

		// 이거를 반복하기
		// 더이상 움직일 수 없을 때 까지
		while (true) {
			int num = 0;
			for (int i = 0; i < list.size(); i++) {
				if (sharkSize > list.get(i).size)
					num++;
			}

			if (num == 0 || list.size() ==0)break;
			//사방향 탐색했을 때 길 막혔으면 
			int direction=0;
			for(int d=0;d<4;d++) {
				int nx = shark[0]+dx[d];
				int ny = shark[1]+dy[d];
				
				if(nx<0 || nx>=N || ny<0 || ny>=N) continue;
				if(map[nx][ny] <= sharkSize) direction++; //길 지나갈 수 있음
			}
			
			if(direction == 0)break;

			Node getMin = new Node(0, 0,Integer.MAX_VALUE);
			int idx = 0;
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i).size >= sharkSize) continue;

				isVisited = new boolean[N][N];
				q.offer(new Node(list.get(i).x, list.get(i).y, 0));
				int size = Integer.MAX_VALUE;

				while (!q.isEmpty()) {
					Node node = q.poll();

					for (int d = 0; d < 4; d++) {
						int nx = node.x + dx[d];
						int ny = node.y + dy[d];

						if (nx < 0 || nx >= N || ny < 0 || ny >= N || isVisited[nx][ny])
							continue;
						if (map[nx][ny] == 9) {
							size = (size>node.size+1)?node.size+1:size;
							break;
						}
						if (map[nx][ny] > sharkSize)
							continue;

						isVisited[nx][ny] = true;
						q.offer(new Node(nx, ny, node.size + 1));
					}

				}
				q.clear();
				// 최단 거리 구했음
				if (getMin.size > size) { //내가 현재 구한 거리가 최소값보다 작으면 갱신
					getMin = new Node(list.get(i).x, list.get(i).y, size);
					idx = i;
				} else if (getMin.size == size) { //최소값이 같으면
					if (getMin.x > list.get(i).x) {//더 위에 있는거
						getMin = new Node(list.get(i).x, list.get(i).y, size);
						idx = i;
					} else if (getMin.x == list.get(i).x && getMin.y > list.get(i).y) { //더 왼쪽에 있는거
						getMin = new Node(list.get(i).x, list.get(i).y, size);
						idx = i;
					}
				}
			}
			if(getMin.size == Integer.MAX_VALUE) getMin.size = 0;
			if(getMin.size != 0) {
				time += getMin.size;
				map[getMin.x][getMin.y] = 0;
				map[shark[0]][shark[1]] =0;
				map[getMin.x][getMin.y] = 9;
				shark[0] = getMin.x;
				shark[1] = getMin.y;
				sharkUp++;
			}
			list.remove(idx); // 리스트에 있는 물고기 하나 지워주고

			if (sharkSize == sharkUp) { // 먹은 개수랑 사이즈랑 똑같아 지면 크기 키워주기
				sharkSize++;
				sharkUp = 0;
			}
			
		}
		// 현재 리스트 중에서 제일 가꺼운거 자리 구하기
		System.out.println(time);
	}


	static class Node {
		int x;
		int y;
		int size;

		public Node(int x, int y, int size) {
			super();
			this.x = x;
			this.y = y;
			this.size = size;
		}
	}
}

 

 

중간에 오류 찾는데 짱 오래걸렸다.

나는 계속 여기에서 오류가 났었다.

내 코드에서는 getMin.size가 Integer.MAX_VALUE로 설정되어 있어서 길이 없으면 Integer.MAX_VALUE가 들어가는 오류가 있었다.

그래서 getMin.size를 0으로 셋팅 해준 뒤에도 오류가 계속 나서 생각해보니

getMin.size가 0 이면 길이 없는 것이니까 map의 배열을 바꿔주면 안됐었다. 

따라서 위의 코드로 수정해주었다.

 

나는 리스트에 현재 물고기들의 위치를 저장해주었다.

Node클래스를 생성하여 현재 좌표와 size를 저장할 수 있게 하였다.

 

그래서 ArrayList에 저장된 값들을 bfs로 탐색하면서 길을 찾아나갔다.

이 문제가 어려운 이유는 구현보다는 추가적으로 예외사항이 많은데 그걸 지켜주는?것이 어려운 것 같다.

'알고리즘 > 백준' 카테고리의 다른 글

[JAVA]백준_2023_신기한 소수  (0) 2021.03.05
[JAVA]백준_1092_배  (0) 2021.03.05
[JAVA] 백준_14501_퇴사  (0) 2021.03.02
[JAVA]백준_8320_직사각형을만드는방법  (0) 2021.02.26
[JAVA]백준_17413_단어뒤집기  (0) 2021.02.25