본문 바로가기
PS 문제 풀이/Baekjoon

[BOJ] 백준 2583 영역 구하기

by 까망 하르방 2021. 2. 23.
반응형

출처: https://www.acmicpc.net/problem/2583

 Input 

5 7 3

0 2 4 4

1 1 2 5

4 0 6 2

 

 Output 

3

1 7 13

직사각형의 정보는 아래와 같습니다.  

문제에서 주어진 인덱스를 아래와 같이 해석해도 무방.

 

3개의 분리된 영역과 그 넓이는 아래와 같습니다.

① 모눈 종이를 순회하며 직사각형으로 안 덮여진 지점을 찾습니다.

② BFS를 통해 분리된 영역을 구분합니다.

③ 분리된 영역의 개수와 각각의 넓이를 구합니다.


import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
 
 
public class Main {
     
    static int[][] arr;
    static List<Integer> areaList;
    static int[] dx, dy;
    static int N, M;
    static Queue<Node> queue;
     
    public static void main(String[] args) {
        Scanner sc = new  Scanner(System.in);
         
        M = Integer.parseInt(sc.next());
        N = Integer.parseInt(sc.next());
        int K = Integer.parseInt(sc.next());
         
        // x,y좌표를 바꿔서 표현
        arr = new int[N][M];
         
        while(K-- > 0) {
            int x1 = Integer.parseInt(sc.next());
            int y1 = Integer.parseInt(sc.next());
            int x2 = Integer.parseInt(sc.next());
            int y2 = Integer.parseInt(sc.next());
             
            for(int i=x1; i<x2; i++) {
                for(int j=y1; j<y2; j++) {
                    arr[i][j] = 1;
                }
            }
        }
         
        // 영역의 개수
        int areaCnt = 0;
         
        // 동서남북(이동 범위)
        dx = new int[] {1, -1, 0, 0};
        dy = new int[] {0, 0, -1, 1};
         
        // BFS를 위한 자료구조 '큐'
        queue = new LinkedList<>();
        areaList = new ArrayList<>();
         
        for(int i=0; i<N; i++) {
            for(int j=0; j<M; j++) {
                // 탐색대상에 해당된다면 BFS 탐색(방문하지 않은 곳)
                if(arr[i][j] == 0) {
 
 
                    // 방문 표시
                    arr[i][j] = 1;
                    queue.add(new Node(i, j));
 
 
                    BFS();
                     
                    // 영역의 개수 올리기
                    areaCnt++;
                }
            }
        }
         
        // 영역의 개수 출력
        System.out.println(areaCnt);
         
        // 영역의 너비를 오름차순 정렬 후 출력
        Collections.sort(areaList);
        while(!areaList.isEmpty()) System.out.print(areaList.remove(0) + " ");
         
         
    }
 
 
    private static void BFS() {
        // 해당 영역의 시작점 영역의 넓이를 '1'로 시작
        int area = 1;
        // 탐색 가능한 모든 지점을 탐색할 때까지
        while(!queue.isEmpty()) {
            Node curNode = queue.poll();
             
            for(int i=0; i<4; i++) {
                int next_x = curNode.x + dx[i];
                int next_y = curNode.y + dy[i];
                 
                // 배열의 범위내에서
                if(next_x < 0 || next_y < 0) continue;
                if(next_x >= N || next_y >= M) continue;
                 
                // 방문한 곳이거나 분리된 지점이라 탐색이 불가능한다면 continue
                if(arr[next_x][next_y] == 1) continue;
                // 방문(탐색) 표시
                arr[next_x][next_y] = 1;
                // 영역의 넓이 값 올리기
                area++;
                // 해당 지점과 연결된 지점을 계속해서 탐색하기 위해 queue에 삽입
                queue.add(new Node(next_x, next_y));
                 
            }
        }
         
        // BFS 탐색이 종료한 뒤 구해진 너비를 넣어둔다.
        areaList.add(area);
         
    }
}
 
 
class Node{
    int x,y;
    public Node(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

 

반응형

'PS 문제 풀이 > Baekjoon' 카테고리의 다른 글

[BOJ] 백준 1932 정수 삼각형  (0) 2021.02.23
[BOJ] 백준 2947 나무 조각  (0) 2021.02.23
[BOJ] 백준 10819 차이를 최대로  (0) 2021.02.23
[BOJ] 백준 4963 섬의 개수  (0) 2021.02.23
[BOJ] 백준 9663 N-Queen  (0) 2021.02.23

댓글