7576번: 토마토
첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토
www.acmicpc.net
얼마 전에 풀었던 문제인데 다시 풀게 되었다.
Solution
이 문제는 BFS를 구현할 줄 안다면 크게 어렵지 않은데, 주의할 점은,
- 이미 익어있는 토마토(즉, 시작점) 가 처음에 여러 개 있을 수 있다.
- 토마토가 몇 초 대에 익는지 기록한다.
이다. 즉, 1번의 경우 여러 토마토가 한 번에 큐에 담겨서 같이 순차적으로 진행될 수 있도록 해야한다는 의미이다.
2번의 경우는, 큐에 담을 때 토마토가 몇 초 대에 익는지 기록하고 나면, 그 토마토에 의해서 익을 다음 토마토들은 이전 토마토가 익은 시간 + 1 이 담기면 된다는 것이다. ( 2초 대에 익은 토마토가 3초 대에 상,하의 토마토를 익힘 )
한 번 풀어봤던 문제라 빠르게 풀었다.
실행 시간을 줄인 것은, 입력 받을 때 익혀야 되는 토마토의 수, 즉 0인 것들의 갯수를 세어서 bfs를 돌고 난 이후에 체크해줘서 2차원 반복을 피할 수 있었다. 입력이 작아서 크게 소용있진 않았지만,,
Source Code
import java.io.*;
import java.util.*;
public class Main {
private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
private static BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
private static int width, height, result, shouldRipeCount;
private static int[][] map;
private static ArrayList<Node> tomatoes;
private static boolean[][] visited;
private static int[] dx = {-1,1,0,0};
private static int[] dy = {0,0,-1,1};
private static class Node {
int x;
int y;
int depth;
public Node(int x, int y, int depth) {
this.x = x;
this.y = y;
this.depth = depth;
}
}
private static void input() throws IOException {
StringTokenizer wh = new StringTokenizer(bufferedReader.readLine());
width = Integer.parseInt(wh.nextToken());
height = Integer.parseInt(wh.nextToken());
map = new int[height][width];
visited = new boolean[height][width];
tomatoes = new ArrayList<>();
for(int i = 0 ; i < height; i++) {
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
for(int j = 0 ; j < width; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 1) {
tomatoes.add(new Node(i,j, 0)); // 이미 익은 토마토들을 담아주고,
visited[i][j] = true; // 방문 처리도 해준다.
} else if(map[i][j] == 0) {
shouldRipeCount++; // 익혀야 하는 토마토 갯수
}
}
}
}
private static boolean bfs() {
ArrayDeque<Node> queue = new ArrayDeque<>();
queue.addAll(tomatoes); // 초기에 익은 토마토들을 먼저 담는다.
int ripeCount = 0; // BFS로 인해 익을 토마토의 갯수를 담는다.
while (!queue.isEmpty()) {
Node s = queue.poll();
int sx = s.x;
int sy = s.y;
int sd = s.depth; // 토마토가 sd 초에 익었다는 것을 나타낸다.
result = sd; // BFS 가 끝날 때,마지막에 익은 토마토는 sd초에 익을 것이므로 계속 대입해준다.
for(int i = 0 ; i < 4; i++) {
int nx = sx + dx[i];
int ny = sy + dy[i];
if(nx < 0 || ny < 0 || nx >= height || ny >= width) continue;
if(visited[nx][ny]) continue;
if(map[nx][ny] == 0) {
map[nx][ny] = 1;
ripeCount++;
visited[nx][ny] = true;
queue.add(new Node(nx, ny, sd + 1));
}
}
}
if(ripeCount == shouldRipeCount) { // 익힌 갯수 = 익혀야 할 갯수라면 true
return true;
} else return false;
}
private static void solve() throws IOException {
if(bfs()) {
System.out.println(result);
} else {
System.out.println(-1);
}
}
public static void main(String[] args) throws IOException {
input();
solve();
}
}
'PS > BOJ' 카테고리의 다른 글
백준 15683번 : 감시 풀이(Java) - DFS (0) | 2021.04.21 |
---|---|
백준 1062번 : 가르침 풀이(Java) - 브루트포스 (0) | 2021.04.18 |
백준 12026 번 : BOJ 거리 풀이(Java) - DP (0) | 2021.03.31 |
백준 1915번 : 가장 큰 정사각형 풀이 (Java) - DP (0) | 2021.03.27 |
백준 11659번 : 구간 합 구하기 4 풀이 (Java) - DP (0) | 2021.03.27 |
최근댓글