알고리즘

백준 2234번 성곽 (JAVA)

박카스마시며코딩 2022. 6. 6. 19:05

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

 

2234번: 성곽

첫째 줄에 두 정수 N, M이 주어진다. 다음 M개의 줄에는 N개의 정수로 벽에 대한 정보가 주어진다. 벽에 대한 정보는 한 정수로 주어지는데, 서쪽에 벽이 있을 때는 1을, 북쪽에 벽이 있을 때는 2를,

www.acmicpc.net

 

저는 BFS를 이용해 문제를 해결하였습니다.

먼저 BFS를 통해 각각의 영역으로 나누고, 그 영역의 크기를 저장하였습니다.

마지막으로 각각의 점을 돌면서 인접한 좌표의 영역이 다르다면 둘의 합이 가장 큰 값을 구하여 마지막의 답을 구하였습니다.

 

package BOJ.bfs;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.function.Function;

public class BOJ_2234 {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        Function<String,Integer> stoi = Integer::parseInt;
        int m = stoi.apply(st.nextToken());
        int n = stoi.apply(st.nextToken());
        int[][] map = new int[n][m];
        for(int i = 0 ; i < n ; i++){
            st = new StringTokenizer(br.readLine());
            for(int j = 0 ; j < m ; j++){
                map[i][j] = stoi.apply(st.nextToken());
            }
        }
        int num = 1;
        int[][] area = new int[n][m];
        int[] results = new int[3];
        List<Integer> size = new ArrayList<>();
        for(int i = 0 ; i < n ; i++){
            for(int j = 0 ; j < m ; j++){
                if(area[i][j] == 0){
                    int nowSize = bfs(i,j,map,n,m,area,num++);
                    results[1] = Math.max(results[1],nowSize);
                    size.add(nowSize);
                    results[0]++;
                }
            }
        }
        for(int i = 0 ; i < n ; i++){
            for(int j = 0 ; j < m ; j++){
                for(int dir = 0 ; dir < 4; dir++){
                    int ny = i + dy[dir];
                    int nx = j + dx[dir];
                    if(checkBound(ny,nx,n,m) && area[ny][nx] != area[i][j]){
                        results[2] = Math.max(results[2], size.get(area[ny][nx]-1) + size.get(area[i][j]-1));
                    }
                }
            }
        }
        for(int result : results){
            System.out.println(result);
        }
    }

    private static final int WEST = 0; // 서
    private static final int NORTH = 1; // 북
    private static final int EAST = 2; // 동
    private static final int SOUTH = 3; // 남

    private static final int[] dy = {0, -1, 0, 1};
    private static final int[] dx = {-1, 0, 1, 0};

    private static final int EMPTY = 0;

    private static int bfs(int y, int x, int[][] map, int n, int m, int[][] area, int num) {
        int result = 1;
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] {y, x});
        area[y][x] = num;
        while(!q.isEmpty()) {
            int[] now = q.poll();
            int nowY = now[0];
            int nowX = now[1];
            for(int dir = 0 ; dir < 4; dir++){
                int isBlock = map[nowY][nowX] & (1 << dir);
                int ny = nowY + dy[dir];
                int nx = nowX + dx[dir];
                if(isBlock == EMPTY && checkBound(ny,nx,n,m) && area[ny][nx] == 0){
                    result++;
                    area[ny][nx] = num;
                    q.offer(new int[] {ny,nx});
                }
            }
        }
        return result;
    }
    private static boolean checkBound(int y, int x, int n, int m){
        if(y >= 0 && y < n && x >= 0 && x < m){
            return true;
        }
        return false;
    }
}