728x90

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

 

2583번: 영역 구하기

첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오

www.acmicpc.net

 

 

 

풀이)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

public class Main_BJ_2583_영역구하기 {
    static int n, m, sum;
    static int[][] map;
    static boolean[][] visited;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    static ArrayList<Integer> areas = new ArrayList<>();
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());
        map = new int[n][m];
        visited = new boolean[n][m];
        for(int i=0; i<k; i++){
            st = new StringTokenizer(br.readLine());
            int ly = Integer.parseInt(st.nextToken());
            int lx = Integer.parseInt(st.nextToken());
            int ry = Integer.parseInt(st.nextToken());
            int rx = Integer.parseInt(st.nextToken());
            for(int x=lx; x<rx; x++){
                for(int y=ly; y<ry; y++){
                    visited[x][y] = true;
                    map[x][y]++;
                }
            }
        }//k

        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(!visited[i][j]) {
                    int area = bfs(i, j);
                    sum++;
                    areas.add(area);
                }
            }
        }
        System.out.println(sum);
        Collections.sort(areas);
        for(int i=0; i<areas.size(); i++)
            System.out.print(areas.get(i)+" ");

    }//main
    private static int bfs(int x, int y){
        int area = 0;
        visited[x][y] = true;
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[] {x, y});

        while(!q.isEmpty()){
            int[] cur = q.poll();
            area++;
            for(int i=0; i<4; i++){
                int nx = cur[0] + dx[i];
                int ny = cur[1] + dy[i];

                if(check(nx, ny) && !visited[nx][ny]){
                    q.offer(new int[] {nx, ny});
                    visited[nx][ny] = true;
                }
            }
        }//while
        return area;
    }//bfs
    private static boolean check(int x, int y) {
        if(x<0 || y<0 || x>=n || y>=m)
            return false;
        return true;
    }
}

만약, 완탐과 dfs, bfs 문제를 많이 풀어봤다면 문제 자체는 어렵지 않다!

다만,,,, 조건을 좀 많이 주의해야해서...ㅎ

 

처음에는 너무 단순히 아래를 0,0 을 잡았다해서 위 아래만 바뀐거라 괜찮아~~ 했는데,,

1. 행과 열이 바뀌어 있는 문제입니다....

2. 최소 좌표와 최대 좌표가 있는데, 최대 좌표를 -1 만큼 탐색하면 일반 탐색과 다를 것이 없습니다.

 

나머지는 입력을 받으면서 직사각형을 그린 영역을 visited 처리해주고,

전체 완탐을 하면서 visited 안 한 곳을 찾아주면 된다!

 

bfs를 통해 visited가 아닌 곳의 영역 수를 구하면 되고, 이는 bfs의 return값을 이용하여 영역을 저장해준다.

그리고 areas라는 ArrayList 배열을 정렬하면 끝!!

728x90

'코테 > 백준' 카테고리의 다른 글

백준 10807 개수 세기(JAVA)  (0) 2023.04.23
백준 10773 제로(JAVA)  (0) 2023.04.21
백준 10951 A+B - 4(JAVA)  (0) 2023.04.18
백준 2468 안전 영역(JAVA)  (0) 2023.04.12
백준 1715 카드 정렬하기(JAVA)  (0) 2023.04.11

+ Recent posts