[BOJ] C++ 2468 "안전 영역" 문제 풀이 _ nov

    반응형

    #INFO

    난이도 : SILVER1

    문제유형 : BFS

    출처 : 2468번: 안전 영역 (acmicpc.net)

     

    2468번: 안전 영역

    재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는

    www.acmicpc.net


    #SOLVE

    특정한 높이에서 물에 잠기지 않은 영역의 최대 개수를 구하는 문제이다. 예를들어 높이가 3 이하인 모든 지점이 물에 잠겼다고 가정하면 아래 그림과 같이 4가지 구역으로 나뉘어 진다. 

    높이가 0부터 보드 내에서 가장 큰 높이인 9까지 모든 경우의 수를 탐색해 가장 나뉘어지는 구역이 많은 케이스를 선택하는 브루트포스 방식으로 문제를 풀이했다.

    #define X first
    #define Y second
    int board[103][103]; // 물의 높이를 저장할 배열
    int rain[103][103]; // 1 : 물에 잠긴 지역 , 0 : 물에 잠기지 않은 지역
    int isVisited[103][103]; // 방문 여부를 저장할 배열
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, -1, 0, 1};

    int board[103][103] : 물의 높이 정보를 저장할 배열이다.

    int rain[103][103] : 각 지역이 물에 잠겼는지 여부를 저장할 배열이다. (1 : 물에 잠긴 지역, 0 : 물에 잠기지 않은 지역)

    int isVisited[103][103] : BFS 알고리즘에서 방문 여부를 저장할 배열이다.

    int dx[4], dy[4] : BFS 알고리즘에서 상하좌우 탐색을 도와줄 변수이다.

     

    	int n;
    	cin >> n;
    	int maxLimit = -1;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < n; j++){
    			cin >> board[i][j];
    			maxLimit = max(board[i][j], maxLimit);
    		}
    	}

    중첩 for문을 통해 높이 정보를 입력받고, 배열 내의 가장 큰 높이를 maxLimit 변수에 저장한다.

     

    int count[maxLimit]; // 모든 높이의 구역의 개수를 저장할 배열
    	for(int limit = 0; limit <= maxLimit; limit++) {
    		// Init Array
    		for(int i = 0; i < n; i++) {
    			fill(rain[i], rain[i] + n, 0);
    			fill(isVisited[i], isVisited[i] + n, 0);
    		}
    		
    		// Check Area
    		for(int i = 0; i < n; i++){
    			for(int j = 0; j < n; j++){
    				if(board[i][j] <= limit) rain[i][j] = 1;
    			}
    		}
     }

    int count[maxLimit] : 모든 높이 (0 ~ 9(maxLimit))의 구역의 개수를 저장할 배열이다.

    // Init Array Part

    fill 함수를 이용해 물에 잠긴 지역 여부를 판별하는 rain 배열과 BFS 알고리즘에서 방문 여부를 판별하는 isVisited 배열을 모두 0으로 초기화한다.

    // Check Area Part

    for문을 돌면서 limit(현재 높이)보다 작은 지역은 모두 잠긴 지역 (rain[i][j] = 1) 으로 지정한다.

     

    		//BFS
    		int cnt = 0;
    		for(int i = 0; i < n; i++) {
    			for(int j = 0; j < n; j++) {
    				queue<pair<int,int>> Q;
    				// 물에 잠긴 지역이거나, 이미 방문한 지역인 경우 cotinue
    				if(rain[i][j] == 1 || isVisited[i][j] == 1) continue;
    				Q.push({i, j});
    				isVisited[i][j] = 1;
    				while(!Q.empty()){
    					auto cur = Q.front();
    					Q.pop();
    					for(int dir = 0; dir < 4; dir++){
    						int nx = cur.X + dx[dir];
    						int ny = cur.Y + dy[dir];
    						if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
    						if(rain[nx][ny] == 1 || isVisited[nx][ny] == 1) continue;
    						isVisited[nx][ny] = 1;
    						Q.push({nx, ny});
    					}
    				}
    				cnt++;
    			}

    전형적인 BFS 풀이이다.

     

    	cout << *max_element(count, count + sizeof(count)/sizeof(int)) << '\n';

    마지막으로 max_element 함수를 이용해 count 배열에 저장된 가장 큰 값을 출력한다.


    #CODE

    #include <bits/stdc++.h>
    using namespace std;
    #define X first
    #define Y second
    int board[103][103]; // 물의 높이를 저장할 배열
    int rain[103][103]; // 1 : 물에 잠긴 지역 , 0 : 물에 잠기지 않은 지역
    int isVisited[103][103]; // 방문 여부를 저장할 배열
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, -1, 0, 1};
    
    int main(int argc, char* argv[]) {
    	ios::sync_with_stdio(0);
    	cin.tie(0);
    	int n;
    	cin >> n;
    	int maxLimit = -1;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < n; j++){
    			cin >> board[i][j];
    			maxLimit = max(board[i][j], maxLimit);
    		}
    	}
    	
    	int count[maxLimit]; // 모든 높이의 구역의 개수를 저장할 배열
    	for(int limit = 0; limit <= maxLimit; limit++) {
    		// Init Array
    		for(int i = 0; i < n; i++) {
    			fill(rain[i], rain[i] + n, 0);
    			fill(isVisited[i], isVisited[i] + n, 0);
    		}
    		
    		// Check Area
    		for(int i = 0; i < n; i++){
    			for(int j = 0; j < n; j++){
    				if(board[i][j] <= limit) rain[i][j] = 1;
    			}
    		}
    
    		//BFS
    		int cnt = 0;
    		for(int i = 0; i < n; i++) {
    			for(int j = 0; j < n; j++) {
    				queue<pair<int,int>> Q;
    				// 물에 잠긴 지역이거나, 이미 방문한 지역인 경우 cotinue
    				if(rain[i][j] == 1 || isVisited[i][j] == 1) continue;
    				Q.push({i, j});
    				isVisited[i][j] = 1;
    				while(!Q.empty()){
    					auto cur = Q.front();
    					Q.pop();
    					for(int dir = 0; dir < 4; dir++){
    						int nx = cur.X + dx[dir];
    						int ny = cur.Y + dy[dir];
    						if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
    						if(rain[nx][ny] == 1 || isVisited[nx][ny] == 1) continue;
    						isVisited[nx][ny] = 1;
    						Q.push({nx, ny});
    					}
    				}
    				cnt++;
    			}
    		}
    		count[limit] = cnt;
    	}
    
    	cout << *max_element(count, count + sizeof(count)/sizeof(int)) << '\n';
    }
    반응형

    댓글

    Designed by JB FACTORY