All :L
[BOJ/Java] 음식물 피하기 (1713) 본문
반응형
1. 문제 분석
문제 개요
- N x M 크기의 격자판에 K개의 음식물 쓰레기가 흩어져 있습니다.
- 각 음식물 쓰레기는 인접한 칸(상, 하, 좌, 우)으로 연결될 수 있으며, 연결된 음식물 쓰레기 덩어리 중 가장 큰 크기를 구하는 문제입니다.
입력 형식
- 첫 번째 줄에 격자의 크기 N, M과 음식물 쓰레기의 수 K가 주어집니다.
- 이후 K개의 줄에 음식물 쓰레기가 위치한 좌표 (r, c)가 주어집니다.
출력 형식
- 연결된 음식물 쓰레기 중 가장 큰 덩어리의 크기를 출력합니다.
2. 알고리즘 종류
이 문제는 BFS(너비 우선 탐색) 알고리즘을 사용하여 연결된 음식물 쓰레기의 크기를 구하는 문제입니다. BFS를 통해 각 쓰레기 덩어리의 크기를 구하고, 그중 최대 크기를 찾는 방식으로 해결합니다.
3. 주요 부분 및 코드 작성 방법
1. BFS 사용
- BFS를 사용하여 각 음식물 쓰레기의 덩어리 크기를 계산합니다.
- 방문하지 않은 음식물 쓰레기 위치에서 BFS를 시작해 연결된 모든 쓰레기를 탐색하고 크기를 셉니다.
2. 최대 크기 업데이트
- 각 BFS 탐색 후, 계산된 덩어리 크기를 갱신하며 최종적으로 가장 큰 크기를 찾습니다.
4. 코드 설명
(1) 메인 함수 (main
)
입력 처리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); // 격자의 행 개수 M = Integer.parseInt(st.nextToken()); // 격자의 열 개수 K = Integer.parseInt(st.nextToken()); // 음식물 쓰레기의 개수
- 첫 번째 줄에서 격자의 크기(N, M)와 음식물 쓰레기의 수(K)를 입력받아 각각의 변수에 저장합니다.
초기화 및 입력된 위치 저장
food = new int[N][M]; // 음식물 쓰레기 위치를 저장하는 2차원 배열 visited = new boolean[N][M]; // 방문 여부를 체크하는 2차원 배열 for(int i = 0; i < K; i++) { st = new StringTokenizer(br.readLine()); int r = Integer.parseInt(st.nextToken()) - 1; // 입력된 행 좌표 int c = Integer.parseInt(st.nextToken()) - 1; // 입력된 열 좌표 food[r][c] = 1; // 해당 위치에 음식물 쓰레기 표시 }
food
배열은 음식물 쓰레기의 위치를 저장하며,visited
배열은 해당 위치를 방문했는지 확인합니다.- K개의 음식물 쓰레기의 위치를 입력받아
food
배열에 표시합니다.
BFS를 통한 덩어리 탐색
for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { if(food[i][j] == 1 && !visited[i][j]) bfs(i, j); } }
- 모든 격자 칸을 순회하며, 음식물 쓰레기가 있고 방문하지 않은 위치를 찾으면 BFS를 시작하여 연결된 덩어리의 크기를 계산합니다.
결과 출력
System.out.println(result); // 가장 큰 덩어리의 크기를 출력
- BFS를 통해 계산된 가장 큰 음식물 쓰레기 덩어리의 크기를 출력합니다.
(2) BFS 함수 (bfs
)
초기화
Queue<Point> q = new LinkedList<>(); visited[x][y] = true; // 시작점을 방문 처리 q.offer(new Point(x, y)); // 큐에 시작점 추가 int cnt = 1; // 현재 덩어리 크기 초기화
- BFS 탐색을 위한 큐를 초기화하고, 시작점을 방문 처리한 후 큐에 넣습니다.
- 덩어리 크기를 나타내는
cnt
변수를 1로 초기화합니다.
BFS 탐색
while(!q.isEmpty()) { Point p = q.poll(); // 큐에서 점을 꺼냄 for(int i = 0; i < 4; i++) { // 4방향 탐색 int nx = p.x + dx[i]; // 다음 탐색할 행 위치 int ny = p.y + dy[i]; // 다음 탐색할 열 위치 if(nx < 0 || nx >= N || ny < 0 || ny >= M || visited[nx][ny] || food[nx][ny] != 1) continue; q.add(new Point(nx, ny)); // 큐에 추가 visited[nx][ny] = true; // 방문 처리 cnt++; // 덩어리 크기 증가 } } result = Math.max(result, cnt); // 최대 덩어리 크기 업데이트
- 큐가 빌 때까지 인접한 칸들을 탐색하여, 범위 내에 있고 방문하지 않았으며 음식물이 있는 경우 큐에 추가하고, 덩어리 크기를 증가시킵니다.
- 탐색이 끝나면
result
변수에 최대 덩어리 크기를 업데이트합니다.
5. 전체 코드
import java.io.*;
import java.util.*;
public class Main {
static int N, M, K; // N: 행, M: 열, K: 음식물 쓰레기 개수
static boolean[][] visited; // 방문 여부를 체크하는 배열
static int[][] food; // 음식물 쓰레기 위치를 나타내는 배열
static int result; // 최대 음식물 쓰레기 덩어리 크기
// 상, 우, 하, 좌 방향을 나타내는 배열
static int[] dx = new int[] {-1, 0, 1, 0};
static int[] dy = new int[] {0, 1, 0, -1};
// 좌표를 나타내는 클래스
static class Point {
int x, y; // x: 행, y: 열
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 입력받은 N, M, K 값을 초기화
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
// 음식물 쓰레기 위치와 방문 여부를 저장하는 배열 초기화
food = new int[N][M];
visited = new boolean[N][M];
// K개의 음식물 쓰레기 위치를 입력받아 배열에 저장
for(int i = 0; i < K; i++) {
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken()) - 1; // 입력받은 행 좌표
int c = Integer.parseInt(st.nextToken()) - 1; // 입력받은 열 좌표
food[r][c] = 1; // 해당 위치에 음식물 쓰레기 표시
}
// 음식물 쓰레기 위치를 탐색하여 연결된 덩어리 크기 계산
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++) {
if(food[i][j] == 1 && !visited[i][j]) bfs(i, j);
}
}
// 결과 출력
System.out.println(result);
}
// BFS 함수: 주어진 위치에서 시작해 연결된 음식물 쓰레기의 크기를 계산
static void bfs(int x, int y) {
Queue<Point> q = new LinkedList<>();
visited[x][y] = true; // 시작점을 방문 처리
q.offer(new Point(x, y)); // 큐에 시작점 추가
int cnt = 1; // 현재 덩어리 크기 초기화
while(!q.isEmpty()) {
Point p = q.poll(); // 큐에서 점을 꺼냄
for(int i = 0; i < 4; i++) { // 4방향 탐색
int nx = p.x + dx[i]; // 다음 탐색할 행 위치
int ny = p.y + dy[i]; // 다음 탐색할 열 위치
// 범위를 벗어나거나, 이미 방문했거나, 음식물 쓰레기가 없는 경우 스킵
if(nx < 0 || nx >= N || ny < 0 || ny >= M || visited[nx][ny] || food[nx][ny] != 1) continue;
q.add(new Point(nx, ny)); // 큐에 추가
visited[nx][ny] = true; // 방문 처리
cnt++; // 덩어리 크기 증가
}
}
result = Math.max(result, cnt); // 최대 덩어리 크기 업데이트
}
}
반응형
'CODING > BOJ' 카테고리의 다른 글
[BOJ/Java] 치즈 (2638) (0) | 2024.08.29 |
---|---|
[BOJ/Java] 섬의 개수 (4963) (0) | 2024.08.28 |
[BOJ/Java] 듣보잡 (1764) (0) | 2024.08.28 |
[BOJ/Java] 파일 정리 (20291) (0) | 2024.08.28 |
[BOJ/Java] 달력 (20207) (0) | 2024.08.28 |
Comments