Algorithm Solving/Java

[BOJ] 백준 1962번 : 그림 - Java

기만나🐸 2024. 9. 9. 17:10

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

 

BFS 풀이

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {

    // 좌표(position) 클래스 선언, 생성자 생성
    static class Pos {
        int y, x;
        public Pos(int y, int x) {
            this.y = y;
            this.x = x;
        }
    }

    // 도화지 정보를 저장하는 2차원 배열 (그래프)
    static int[][] map;

    // 도화지 노드를 방문했는지 확인하는 2차원 배열
    static boolean[][] visited;

    // 상하좌우 y 변경 값
    static int[] dy = {-1, 1, 0, 0};
    // 상하좌우 x 변경 값
    static int[] dx = {0, 0, -1, 1};
    // (x + dx[i], y + dy[i]) 로 좌표 위치를 변경 
    // (x+0, y-1) : 위로 이동하는 좌표 계산(상)
    // (x+0, y+1) : 아래로 이동하는 좌표 계산(하)
    // (x-1, y+0) : 왼쪽으로 이동하는 좌표 계산(좌)
    // (x+1, y+0) : 오른쪽으로로 이동하는 좌표 계산(우)

    // 문제에서 주어진 세로크기 n, 가로크기 m, 가장 넓은 그림의 넓이 max_width
    static int n, m, max_width = 0;

    public static void main(String[] args) throws IOException {
        // 입력값 처리할 버퍼리더
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 결과값 출력할 버퍼라이터
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        // 문자열 토큰형식으로 다룰 스트링토커나이저
        StringTokenizer st = new StringTokenizer(br.readLine()," ");

        // 입력값 저장
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        map = new int[n][m];
        visited = new boolean[n][m];

        // 도화지 정보 저장
        for (int i=0; i<n; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            for (int j=0; j<m; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        // 그림 개수 저장할 변수 선언
        int cnt = 0;

        // 방문하지 않은 칠해진 노드(값이 1)를 기준으로 BFS 탐색
        for (int i=0; i<n; i++) {
            for (int j=0; j<m; j++) {
                if (map[i][j] == 1 && !visited[i][j]) {
                    // 값이 1이고 방문하지 않은 노드일 경우 BFS 탐색
                    visited[i][j] = true;   // 다음에는 방문하지 않도록 방문 확인
                    bfs(i,j);               // BFS 탐색 호출
                    cnt ++;                 // 그림 개수 증가
                }
            }
        }

        //그림 개수와 그림 최대 넓이 BufferedWriter 저장
        StringBuilder sb = new StringBuilder();
        sb.append(cnt).append("\n").append(max_width);
        bw.write(sb.toString());
        bw.flush();		//결과 출력
        bw.close();
        br.close();
    }

    // BFS 탐색을 위한 함수
    static void bfs(int y, int x) {
        Queue<Pos> queue = new ArrayDeque<>();
        queue.add(new Pos(y, x));   // 시작 위치 Queue에 저장
        int width = 1;

        // 탐색
        while (!queue.isEmpty()) {
            Pos cur = queue.poll(); // 큐의 첫번째 요소로 초기화 (큐의 첫번째 요소는 삭제 됨)
            // 상하좌우 탐색 진행
            for (int i=0; i<4; i++) {
                int tempY = cur.y + dy[i];
                int tempX = cur.x + dx[i];
                // 해당 좌표가 방문하지 않은 1일 경우
                if (inSpace(tempY, tempX) && !visited[tempY][tempX] && map[tempY][tempX] == 1) {
                    visited[tempY][tempX] = true;       // 방문 확인
                    queue.add(new Pos(tempY, tempX));   // Queue에 다음 방문 노드로 저장
                    width ++;
                }
            }
        }
        // 방금 구한 넓이가 최대 넓이인지 확인
        max_width = Math.max(max_width, width);
    }

    // (y, x)가 도화지에 존재하는지 확인하는 함수
    static boolean inSpace(int y, int x) {
        if(y >= 0 && x >= 0 && y < n && x < m)
            return true;        //도화지가 존재할 때
        else 
            return false;		//도화지에 존재하지 않을 때
    }
}