[規格]2468セキュリティエリア(Java)


質問リンク


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

もんだいぶんせき

  • 地図(NXN)のいずれかの一定の高さより低い点=>水没
  • エリア:上下左右に接続されています.上下左右接続なら同じ領域です.

    上記の場合,領域の個数は5個である.
  • ある地域の高度な情報を得たとき、雨季に浸水しない安全区域の最大個数はいくらですか?
  • 注意
  • !どの地域でも水没しない可能性がある=>水の高さが0の場合も考えられる.
  • 入力

  • N (2<= N <= 100)
  • NxNの高さ情報(1<=1格<=100)
  • しゅつりょく

  • 第1行は雨季の浸水しない安全区域の最大数を出力する.
  • に答える


  • 入力を受けて、地図の最大高さ(maxHeight)を探します.
  • 0–100、すべての高さをチェックしない

  • 0~maxHeightの間、セキュリティ領域の数を計算します.

  • ch配列を宣言してロックまたはアクセスされた領域を示す

  • 未発見の領域がある場合は、数を1つ追加した後、DFSで上下左右に接続されている部分をチェックします.
    private static int countRegion(int height) {
        int count = 0;
        
        //물에 잠김 or 방문한 영역을 표시할 ch 배열
        boolean[][] ch = new boolean[n][n];
    
    				//물에 잠긴 영역 표시
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                if(map[i][j]<=height)
                    ch[i][j] = true;
    
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++){
            	//방문하지 않은 지역이 있다면
                if(ch[i][j]==false){
                    count++; //개수 추가
                    DFS(i, j, ch); //연결된 부분 체크 
                }
            }
    
        return count;
    }
    
    private static void DFS(int r, int c, boolean[][] ch) {
    	//상하좌우로 탐색한다.
        for(int i=0; i<4; i++){
            int nr = r+ dr[i];
            int nc = c+dc[i];
    
            if(nr<0 || nr>=n || nc<0 || nc>=n) continue;
            if(ch[nr][nc]==false){
                ch[nr][nc]= true;
                DFS(nr, nc, ch);
            }
        }
    }
  • 完全なコード

    import java.util.*;
    
    public class Main {
        //상하좌우 탐색에 사용할 변위
        static int[] dr = {-1, 0, 1, 0};
        static int[] dc = {0, 1, 0, -1};
    
        static int n;
        static int[][] map;
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            n = scanner.nextInt();
            map = new int[n][n];
            int maxHeight = Integer.MIN_VALUE;
            int answer = Integer.MIN_VALUE;
    
            //지도를 입력 받으며 최대 높이 갱신
            for(int i=0; i<n; i++){
                for(int j=0; j<n; j++){
                    map[i][j] = scanner.nextInt();
                    maxHeight = Math.max(maxHeight, map[i][j]);
                }
            }
    
            //0 ~ maxHeight 동안 안전 영역의 개수를 센다.
            for(int i=0; i<=maxHeight; i++){
                //안전 영역의 최대 개수 갱신
                answer = Math.max(countRegion(i), answer);
            }
            System.out.println(answer);
        }
    
        private static int countRegion(int height) {
            int count = 0;
    
            //물에 잠김 or 방문한 영역을 표시할 ch 배열
            boolean[][] ch = new boolean[n][n];
    
            //물에 잠긴 영역 표시
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                    if(map[i][j]<=height)
                        ch[i][j] = true;
    
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++){
                    //방문하지 않은 지역이 있다면
                    if(ch[i][j]==false){
                        count++; //개수 추가
                        DFS(i, j, ch); //연결된 부분 체크
                    }
                }
    
            return count;
        }
    
        private static void DFS(int r, int c, boolean[][] ch) {
            //상하좌우로 탐색한다.
            for(int i=0; i<4; i++){
                int nr = r+ dr[i];
                int nc = c+dc[i];
    
                if(nr<0 || nr>=n || nc<0 || nc>=n) continue;
                if(ch[nr][nc]==false){
                    ch[nr][nc]= true;
                    DFS(nr, nc, ch);
                }
            }
        }
    }