알고리즘/BOJ

[c/c++] 백준/BOJ 2573번 문제 - 빙산

wonjun.Aden 2022. 3. 29. 16:34

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

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

문제

문제풀이

#include <bits/stdc++.h>
using namespace std;

int board[302][302];
int vis[302][302];

int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};



//빙산
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,m;
    cin >> n >> m;

    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin >> board[i][j];
        }
    }
    //연도
    int year_count=0;
    //빙산을 녹이면서 분리되냐 안되냐를 두고 카운트해야함.
    while(true){
        
        
        //방문 초기화
        for(int i=0;i<n;i++){
            fill(vis[i],vis[i]+m,0);
        }

        //빙산이 2개로 쪼개지는지 확인
        int tmp_cnt=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                //보드가 0보다 크고 vis이 0인경우?
                if(board[i][j] != 0 && vis[i][j]==0){
                    queue<pair<int,int>> Q;
                    Q.push({i,j});
                    vis[i][j]=1;
                    while (!Q.empty())
                    {
                        auto cur = Q.front();Q.pop();
                        for(int dir=0;dir<4;dir++){
                            int nx = cur.first+dx[dir];
                            int ny = cur.second+dy[dir];
                            if(nx <0 || nx >=n || ny < 0 || ny >= m)continue;
                            if(board[nx][ny]==0 || vis[nx][ny] == 1) continue;
                            Q.push({nx,ny});
                            vis[nx][ny] = 1;
                        }

                    }
                    tmp_cnt++;
                }
            }
        }

        //쪼개지면 연도 출력
        if(tmp_cnt >=2){
            cout << year_count;
            break;
        }else if(tmp_cnt == 0){
            cout << 0;
            break;
        }

        //연도 더하기
        year_count++;


        //안 쪼개지면 다시 빙산 1씩 빼기부터 되돌기
        //빙산 0이 저장된 개수만큼 빼기
        //주변 바다에 접하는 수를 2차원 배열에 모아둿다가 한번에 빼야 함.
        // (힌트 중요)그렇지 않으면 순차적으로 0이 더해져서 빼짐.
        int zero[303][303]={0};
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j] == 0) continue;
                for(int dir=0; dir < 4;dir++){
                    int nx = i + dx[dir];
                    int ny = j + dy[dir];
                    //범위안에 들어오고, board[i][j] == 0 일때 지정된 개수만큼 빼줘야 함
                    if(nx >= 0 && nx < n && ny >=0 && ny <m && board[nx][ny]==0) {
                        zero[i][j]++;
                    }
                }
            }
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++)
            board[i][j] = max(0, board[i][j] - zero[i][j]);    
        }

    }



    return 0;
}

/* 
5 7
0 0 0 0 0 0 0
0 3 6 0 6 7 0
0 3 0 0 0 10 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0


 */

 

문제의 포인트

  • 빙산을 계속해서 녹이면서 BFS를 계속 실행해야함.
  • 빙산을 녹일 때 주변 바다의 개수를 미리 계산하여 한번에 빼야 정확함.
반응형