All :L

[BOJ/Java] 음식물 피하기 (1713) 본문

CODING/BOJ

[BOJ/Java] 음식물 피하기 (1713)

ofijwe 2024. 8. 28. 17:30
반응형

음식물 피하기 (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