[C++] 백준/Gold/2573. 빙산

2024. 12. 26. 21:09·C++/Algorithm

문제: 빙산 (백준 2573번)

간만의 구현 문제이다. 구현 문제는 말 그대로 구현하는 데 시간이 많이 걸리기 때문에 사용하는 알고리즘 자체는 크게 어렵지 않은 경우가 많다. 이번 문제도 그런 케이스이며, 전체적인 로직은 다음과 같다.

문제 의도

  • 배열에 1 이상의 수가 남아있는 동안 반복
    • time을 증가시키고
    • 2차원 배열을 돌며 상하좌우의 0의 개수와 해당 좌표를 저장
    • 저장해둔 0의 개수만큼 해당 좌표의 값을 감소 (0 미만이 되지 않도록)
    • 2차원 배열을 돌며 BFS로 그룹 개수 체크
    • 그룹 개수가 2개 이상이면 반복문을 정지
  • 배열의 1 이상의 수가 있으면 time을 출력
  • 아니면 0을 출력

알고리즘 개요

  1. 시간(time) 증가
    • 매번 반복할 때마다 시간을 증가시킨다.
  2. 녹을 빙산 계산
    • 각 좌표에서 상하좌우로 바다가 몇 칸 있는지 계산하여, 그 수만큼 빙산을 녹인다.
    • 이때 빙산의 크기는 0 미만이 될 수 없으므로 clamp를 사용하여 값을 0과 10 사이로 제한한다.
  3. 빙산 그룹 개수 체크
    • BFS를 사용하여 얼음 덩어리(빙산)가 몇 개로 분리되는지 확인한다.
    • 만약 2개 이상의 덩어리가 되면 더 이상 진행할 수 없고 반복문을 종료한다.
  4. 사이클 종료 여부 확인
    • 모든 얼음이 녹았으면 0을 출력하고, 여전히 얼음이 남아있으면 time을 출력한다.

코드 구현

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

bool Check(vector<vector<int>> &v) {
    for (auto& i : v) {
        for (auto& j : i) {
            if (j > 0) return true;
        }
    }
    return false;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> v(n, vector<int>(m));
    
    // 입력 받기
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> v[i][j];
        }
    }

    int time = 0;
    int offset[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
    vector<vector<bool>> ocean(n, vector<bool>(m));
    ocean[0][0] = true;

    while (Check(v)) {
        time++;

        // 녹을 빙산 계산
        vector<tuple<int, int, int>> ocean;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (!v[i][j]) continue;
                int sum = 0;
                for (int k = 0; k < 4; k++) {
                    int xx = j + offset[k][0];
                    int yy = i + offset[k][1];
                    if (xx < 0 || xx >= m || yy < 0 || yy >= n || v[yy][xx]) continue;
                    sum++;
                }
                ocean.push_back({ i, j, sum });
            }
        }

        // 계산된 결과값 적용
        for (auto& i : ocean) {
            int x, y, cost; tie(y, x, cost) = i;
            v[y][x] = clamp(v[y][x] - cost, 0, 10);
        }

        // 그룹 개수 체크
        vector<vector<bool>> visited(n, vector<bool>(m));
        int iceberg = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (!v[i][j] || visited[i][j]) continue;
                iceberg++;
                queue<pair<int, int>> q;
                q.push({ i, j });
                visited[i][j] = true;
                while (!q.empty()) {
                    int x, y; tie(y, x) = q.front();
                    q.pop();
                    for (int k = 0; k < 4; k++) {
                        int xx = x + offset[k][0];
                        int yy = y + offset[k][1];
                        if (xx < 0 || xx >= m || yy < 0 || yy >= n) continue;
                        if (v[yy][xx] && !visited[yy][xx]) {
                            visited[yy][xx] = true;
                            q.push({ yy, xx });
                        }
                    }
                }
            }
        }

        // 2개 이상의 그룹이 생기면 종료
        if (iceberg > 1) break;
    }

    // 모든 얼음이 녹았으면 0, 아니면 time 출력
    if (Check(v)) cout << time;
    else cout << 0;
}

주요 설명

  1. Check 함수:
    • 배열을 돌면서 얼음이 하나라도 남아있는지 확인한다. 남아있다면 true, 아니면 false를 반환한다.
  2. 녹을 빙산 계산:
    • 각 빙산에서 상하좌우로 바다가 몇 칸 있는지 계산하고, 그 수만큼 빙산을 녹인다. 이때 빙산의 크기는 0 이상이어야 하므로 clamp 함수를 사용하여 값을 0과 10 사이로 제한한다.
  3. 그룹 개수 체크:
    • BFS를 사용하여 얼음 덩어리(빙산)가 몇 개로 분리되는지 확인한다.
    • iceberg 변수로 그룹의 개수를 세고, 2개 이상의 그룹이 생기면 반복문을 종료한다.
  4. 최종 출력:
    • 모든 얼음이 녹았다면 0을 출력하고, 그렇지 않으면 time을 출력한다.

'C++ > Algorithm' 카테고리의 다른 글

[C++] 백준/Gold/17143. 낚시왕  (0) 2025.01.09
[C++] 백준/Gold/7579. 앱  (0) 2024.12.30
[C++] 백준/Gold/20040. 사이클 게임  (0) 2024.12.24
[C++] Intro sort 인트로 정렬 C++  (0) 2024.12.23
[C++] 백준/Gold/17404. RGB거리 2  (0) 2024.12.20
'C++/Algorithm' 카테고리의 다른 글
  • [C++] 백준/Gold/17143. 낚시왕
  • [C++] 백준/Gold/7579. 앱
  • [C++] 백준/Gold/20040. 사이클 게임
  • [C++] Intro sort 인트로 정렬 C++
돼지표
돼지표
https://github.com/wkdgns135
  • 돼지표
    돼지표 개발 스토리
    돼지표
  • 전체
    오늘
    어제
    • 분류 전체보기 (97)
      • C++ (58)
        • Algorithm (52)
      • Python (1)
      • Machine Learning (2)
      • Computer Graphics (4)
        • Curly Hair Simulation (2)
      • GPU Programming (11)
        • CUDA basic (7)
        • CUDA fluidsGL (4)
      • Unreal 5 (19)
        • Troubleshooting (4)
        • FPS Shooting (5)
        • Study (8)
        • EOS (1)
      • Computer Science (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    그리디 알고리즘
    Algorithm
    위상 정렬
    FPS
    Fluid Simulation
    그래프 탐색
    CUDA
    unreal 5
    아이작 맵 생성
    수학
    GPU Programming
    자료 구조
    dp
    그래프 이론
    구현
    BFS
    Rendering Pipeline
    UE5
    C++
    OpenGL
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
돼지표
[C++] 백준/Gold/2573. 빙산
상단으로

티스토리툴바