https://www.acmicpc.net/problem/1926
1926번: 그림
어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로
www.acmicpc.net
알고리즘 분류
- 너비우선 탐색
- 깊이우선 탐색
- 그래프 탐색
풀이
그래프 탐색 문제이다. 저는 너비 우선 탐색(bfs)를 이용해 풀었다.
먼저 초기화 작업이다.
x 축 좌표로 이동할 int형 배열 dx,
y 축 좌표로 이동할 int형 배열 dy,
그림이 그려져 있는지 안그려져 있는지 (0과 1인지) 을 구분하는 2차원 배열 map,
방문했는지 안했는지 구분하는 boolean형 2차원 배열 visited,
그리고 너비 우선 탐색에 사용할 Queue이다.
private static final int[] dx = {-1, 0, 1, 0}; private static final int[] dy = {0, 1, 0, -1}; private static int[][] map; private static boolean [][] visited; private static Queue<int []> queue;
입력을 받은 후 for 루프문을 돌면서 그림이 그려져 있거나 ( 값이 1일 때 )
아직 방문하지 않은 노드면 i, y ( x축, y축 ) 를 매개변수로 넣고 bfs메서드를 실행하도록 하였다.
그림 넓이를 반환해서 area에 담은 후 list에 추가 했다.
for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[0].length; j++) { if(map[i][j] == 1 && !visited[i][j]){ int area = bfs(i, j); list.add(area); } // if } // for } // for
bfs 메서드 이다.
매개변수로 받은 i, y (x 좌표, y좌표) 값을 큐에 담은 후 방문 처리(visited[][] = true)를 해준다.
그리고 while 루프문을 돌면서 움직일 x 좌표, y좌표를 구한 뒤
그 좌표 들이 0보다 작거나 배열의 크기보다 크면 continue를 하도록 조건문을 추가 하였다.
만약 그림이 그려져 있거나(map[][] == 1) 아직 방문하지 않은 좌표(!visited[][])라면
queue에 그 좌표들을 배열로 넣어 다시 탐색하게 하고 방문처리도 해준다.
그리고 탐색한 그 좌표도 그림이 그려져 있는 곳 이므로 sum += 1 처리를 해줬다. (그림 크기가 1증가한다.)
public static int bfs(int x, int y){ queue = new LinkedList<>(); queue.add(new int[]{x, y}); // 현재 좌표에서 탐색해야 하므로 queue에 넣는다 visited [x][y] = true; // 방문 처리 int sum = 1; while (!queue.isEmpty()){ int[] current = queue.poll(); int cx = current[0]; int cy = current[1]; for (int i = 0; i < 4; i++) { int mx = cx + dx[i]; // 움직일 x 좌표 int my = cy + dy[i]; // 움직일 y 좌표 if (mx < 0 || mx >= map.length || my < 0 || my >= map[0].length){ continue; } if(map[mx][my] == 1 && !visited[mx][my]){ queue.add(new int[]{mx, my}); visited[mx][my] = true; sum++; } // if } // for } // while return sum; } // bfs
아래는 전체 정답 코드이다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { private static final int[] dx = {-1, 0, 1, 0}; private static final int[] dy = {0, 1, 0, -1}; private static int[][] map; private static boolean [][] visited; private static Queue<int []> queue = new LinkedList<>();; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int m = Integer.parseInt(st.nextToken()); map = new int[n][m]; visited = new boolean[n][m]; for (int i = 0; i < map.length; i++) { String temp[] = br.readLine().split(" "); for (int j = 0; j < temp.length; j++) { map[i][j] = Integer.parseInt(temp[j]); } // for } // for List<Integer> list = new ArrayList<>(); for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[0].length; j++) { if(map[i][j] == 1 && !visited[i][j]){ int area = bfs(i, j); list.add(area); } // if } // for } // for Collections.sort(list); System.out.println(list.size()); if (list.isEmpty() ){ System.out.println("0"); }else{ System.out.println(list.get(list.size()-1)); } } // main public static int bfs(int x, int y){ queue.add(new int[]{x, y}); visited [x][y] = true; int sum = 1; while (!queue.isEmpty()){ int[] current = queue.poll(); int cx = current[0]; int cy = current[1]; for (int i = 0; i < 4; i++) { int mx = cx + dx[i]; int my = cy + dy[i]; if (mx < 0 || mx >= map.length || my < 0 || my >= map[0].length){ continue; } if(map[mx][my] == 1 && !visited[mx][my]){ queue.add(new int[]{mx, my}); visited[mx][my] = true; sum++; } // if } // for } // while return sum; } // bfs }
'BOJ, Programmers' 카테고리의 다른 글
[Java] 백준 1449번 (수리공 항승) (0) | 2024.04.06 |
---|---|
[Java] 백준 1577 (도로의 개수) (2) | 2024.04.05 |
[Java] 프로그래머스 (이중우선 순위 큐 ) (0) | 2024.04.05 |
[Java] 백준 2822 (점수 계산) (0) | 2024.04.05 |
[JAVA] 백준 1041 (주사위) (0) | 2024.04.05 |