본문 바로가기

백준/그래프

[KOI] 백준 2638 - 치즈

728x90

www.acmicpc.net/problem/2638

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5≤N, M≤100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표

www.acmicpc.net

 

KOI 중등부 치즈문제이다.

 

중등 치즈에서는 치즈 격자가 외부 공기와 두변 이상 접촉해야 녹는다고 하며 치즈를 모두 녹이는데 필요한 시간을 구해야 한다.

 

또한 모눈 종이에 가장자리에는 치즈가 놓이지 않는다는 조건이 있다.

 

이를 공기의 관점으로 접근하면 문제를 해결할 수 있다.

 

1. BFS로 공기를 흘려보낸다. 가장자리에는 치즈가 놓이지 않으므로 탐색 시작점은 (0, 0)이 적절할 것이다.

공간을 탐색하면서 치즈와 접촉할 때마다 해당 치즈의 공기 접촉 횟수를 기록한다.

 

2. 탐색이 완전히 끝난 후 2번 이상 공기와 접촉한 치즈는 녹는 치즈이므로 배열에 이를 반영한다.

이 과정을 치즈가 다 녹을 때까지 반복하면 된다.

 

전체 코드

더보기
#include <bits/stdc++.h>

using namespace std;

int cheese[100][100];
int meltdown[100][100];
int visit[100][100];
int mx[4] {0, 0, 1, -1};
int my[4] {1, -1, 0, 0};

int remain = 0;
int remain_past = 0;
int cnt = 0;

vector<vector<int>> airflow(int r, int c)
{
    memset(meltdown, 0, sizeof meltdown);
    memset(visit, 0, sizeof visit);
    vector<vector<int>> bounding;
    queue<vector<int>> dimention;
    dimention.push({0, 0});
    visit[0][0] = 1;
    
    while (!dimention.empty())
    {
        vector<int> curr = dimention.front();
        dimention.pop();
        
        for (int i = 0; i < 4; ++i)
        {
            int nx(mx[i] + curr[0]), ny(my[i] + curr[1]);
            if (nx < 0 || ny < 0 || nx >= r || ny >= c || visit[nx][ny])
                continue;

            if (cheese[nx][ny])
                ++meltdown[nx][ny];
            else
            {
                dimention.push({nx, ny});
                visit[nx][ny] = 1;
            }
        }
    }
    
    for (int j = 0; j < r; ++j)
        for (int k = 0; k < c; ++k)
            if (meltdown[j][k] >= 2)
                bounding.push_back({j, k});
    
    return bounding;
}

int main() 
{
    memset(cheese, -1, sizeof cheese);
    int r, c; cin >> r >> c;

    for (int i = 0; i < r; ++i)
        for (int j = 0; j < c; ++j)
        {
            cin >> cheese[i][j];
            if (cheese[i][j])
                ++remain;
        }

    remain_past = remain;

    while (remain)
    {
        vector<vector<int>> bounding = airflow(r, c);
        
        remain_past = remain;
        remain -= bounding.size();
        
        for (int i = 0; i < bounding.size(); ++i)
            cheese[bounding[i][0]][bounding[i][1]] = 0;
        ++cnt;
    }

    cout << cnt;    
}

728x90

'백준 > 그래프' 카테고리의 다른 글

백준 1738 - 골목길  (0) 2020.10.01
백준 11779 - 최소비용 구하기 2  (0) 2020.08.13
[ICPC] 백준 5719 - 거의 최단 경로  (0) 2020.08.13
[ICPC] 백준 9019 - DSLR  (0) 2020.06.16
백준 - 1219 : 오민식의 고민  (0) 2019.09.08