일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프로그래머스 자바
- index of
- COS Pro
- lv0
- 이진수 변환
- 삼각형의 완성조건
- 프로그래머스 문자열 정렬
- 오름차순 정렬
- Programmers
- 버퍼
- 백준
- SWEA
- 문자열
- 클라이언트
- 스프링부트 도커 배포
- 스프링부트 도커로 배포
- 알고리즘
- 프로그래머스 풀이
- Stack
- StringTokenizer
- 백준 N과 M 자바
- 스택
- 자바
- Queue
- 프로그래머스
- 스프링부트 도커
- java
- 큐
- Lv1
- lv2
- Today
- Total
mun dev
[백준] 2583 영역 구하기 자바(Java) 본문
문제설명
눈금의 간격이 1인 M×N(M,N≤100)크기의 모눈종이가 있다. 이 모눈종이 위에 눈금에 맞추어 K개의 직사각형을 그릴 때, 이들 K개의 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어진다.
예를 들어 M=5, N=7 인 모눈종이 위에 <그림 1>과 같이 직사각형 3개를 그렸다면, 그 나머지 영역은 <그림 2>와 같이 3개의 분리된 영역으로 나누어지게 된다.
<그림 2>와 같이 분리된 세 영역의 넓이는 각각 1, 7, 13이 된다.
M, N과 K 그리고 K개의 직사각형의 좌표가 주어질 때, K개의 직사각형 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어지는지, 그리고 분리된 각 영역의 넓이가 얼마인지를 구하여 이를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오른쪽 위 꼭짓점의 x, y좌표값이 빈칸을 사이에 두고 차례로 주어진다. 모눈종이의 왼쪽 아래 꼭짓점의 좌표는 (0,0)이고, 오른쪽 위 꼭짓점의 좌표는(N,M)이다. 입력되는 K개의 직사각형들이 모눈종이 전체를 채우는 경우는 없다.
출력
첫째 줄에 분리되어 나누어지는 영역의 개수를 출력한다. 둘째 줄에는 각 영역의 넓이를 오름차순으로 정렬하여 빈칸을 사이에 두고 출력한다.
풀이
문제를 보고 dfs로 풀어야겠다 생각했지만 bfs 풀이에 익숙해지기 위해 bfs로 먼저 풀이해보고 dfs도 풀이해봤다.
영역 나와 있는 그림을 보면 평소와 다르게 (0,0)이 왼쪽 아래 끝에서 시작하고 오른쪽 위가 마지막 지점이기 때문에
이 부분에 대해 좀 고민을 했지만 원래 사각형의 뒤집은 모습이니 x와 y를 바꿔주어 값을 넣어주면 된다.
우선, 상, 하, 좌, 우로 탐색해야 하기 때문에 dx, dy배열을 선언 해주었다.
public static int dx[]={0,0,1,-1};
public static int dy[]={1,-1,0,0};
minX와 maxX이렇게 작은 값과 큰 값을 구해주고 y도 마찬 가지로 해준다.
해당 부분들을 1로 채워주고 크기 만큼 for 문을 돌며 채워지지 않은 0의 값이라면 bfs를 호출해서 구현하였다.
for(int i=0; i<k; i++){
st=new StringTokenizer(br.readLine());
int x1=Integer.parseInt(st.nextToken());
int y1=Integer.parseInt(st.nextToken());
int x2=Integer.parseInt(st.nextToken());
int y2=Integer.parseInt(st.nextToken());
int minX=Math.min(x1,x2);
int maxX=Math.max(x1,x2);
int minY=Math.min(y1,y2);
int maxY=Math.max(y1,y2);
for(int j=minX; j<maxX; j++){
for(int h=minY; h<maxY; h++){
arr[h][j]=1;
}
}
}
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(arr[i][j]==0){
bfs(i,j);
list.add(cnt);
cnt=0;
}
}
}
dfs도 풀이는 비슷하고 visited 배열 선언과 방문하지 않았고 해당 부분이 0이라면 재귀호출로 구현하였다.
통과한 코드 ✅
- bfs 풀이
import java.util.*;
import java.io.*;
public class Main {
public static int arr[][];
public static int n,m,k,cnt;
public static int dx[]={0,0,1,-1};
public static int dy[]={1,-1,0,0};
public static class Node{
int x;
int y;
public Node(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());
LinkedList<Integer> list=new LinkedList<>();
m=Integer.parseInt(st.nextToken());
n=Integer.parseInt(st.nextToken());
k=Integer.parseInt(st.nextToken());
arr= new int[m][n];
for(int i=0; i<k; i++){
st=new StringTokenizer(br.readLine());
int x1=Integer.parseInt(st.nextToken());
int y1=Integer.parseInt(st.nextToken());
int x2=Integer.parseInt(st.nextToken());
int y2=Integer.parseInt(st.nextToken());
int minX=Math.min(x1,x2);
int maxX=Math.max(x1,x2);
int minY=Math.min(y1,y2);
int maxY=Math.max(y1,y2);
for(int j=minX; j<maxX; j++){
for(int h=minY; h<maxY; h++){
arr[h][j]=1;
}
}
}
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(arr[i][j]==0){
bfs(i,j);
list.add(cnt);
cnt=0;
}
}
}
Collections.sort(list);
System.out.println(list.size());
for(int i: list){
System.out.print(i+" ");
}
}
public static void bfs(int x, int y){
Queue<Node> queue= new LinkedList<>();
queue.offer(new Node(x,y));
arr[x][y]=1;
cnt++;
while(!queue.isEmpty()) {
Node node=queue.poll();
for (int i = 0; i < 4; i++) {
int cx = node.x + dx[i];
int cy = node.y + dy[i];
if (cx >= 0 && cy >= 0 && cx < m && cy < n) {
if (arr[cx][cy] == 0) {
arr[cx][cy] = 1;
queue.offer(new Node(cx, cy));
cnt++;
}
}
}
}
}
}
- dfs 풀이
import java.util.*;
import java.io.*;
public class Main {
public static int arr[][];
public static boolean visited[][];
public static int n,m,k,cnt;
public static int dx[]={0,0,1,-1};
public static int dy[]={1,-1,0,0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st=new StringTokenizer(br.readLine());
LinkedList<Integer> list=new LinkedList<>();
m=Integer.parseInt(st.nextToken());
n=Integer.parseInt(st.nextToken());
k=Integer.parseInt(st.nextToken());
arr= new int[m][n];
visited=new boolean[m][n];
for(int i=0; i<k; i++){
st=new StringTokenizer(br.readLine());
int x1=Integer.parseInt(st.nextToken());
int y1=Integer.parseInt(st.nextToken());
int x2=Integer.parseInt(st.nextToken());
int y2=Integer.parseInt(st.nextToken());
int minX=Math.min(x1,x2);
int maxX=Math.max(x1,x2);
int minY=Math.min(y1,y2);
int maxY=Math.max(y1,y2);
for(int j=minX; j<maxX; j++){
for(int h=minY; h<maxY; h++){
arr[h][j]=1;
}
}
}
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(!visited[i][j]&&arr[i][j]==0){
dfs(i,j);
list.add(cnt);
cnt=0;
}
}
}
Collections.sort(list);
System.out.println(list.size());
for(int i: list){
System.out.print(i+" ");
}
}
public static void dfs(int x, int y){
visited[x][y]=true;
cnt++;
for(int i=0; i<4; i++){
int cx=x+dx[i];
int cy=y+dy[i];
if(cx>=0 && cy>=0 && cx<m && cy<n){
if(arr[cx][cy]==0 && !visited[cx][cy]){
dfs(cx,cy);
}
}
}
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 1389 케빈 베이컨의 6단계 법칙 자바(Java) (1) | 2023.10.10 |
---|---|
[백준] 10026 적록색 약 자바(Java) (0) | 2023.10.07 |
[백준] 2644 촌수계산 자바(Java) (1) | 2023.10.05 |
[백준] 4963 섬의 개수 자바(Java) (1) | 2023.10.04 |
[백준] 2580 스도쿠 자바(Java) (0) | 2023.10.01 |