문제 링크

  • 나의 풀이

모든 높이를 순회하며 최대 안전지대의 수를 계산했다.

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>

using namespace std;

constexpr int dr[4] = { -1, 1, 0, 0 };
constexpr int dc[4] = { 0, 0, -1, 1 };

int m[100][100], chk[100][100];
int N, M;

bool isVaild(const int& r, const int& c)
{
    if (r < 0 || r >= N || c < 0 || c >= N || chk[r][c])
        return false;
    return true;
}

int bfs(int lv)
{
    int ret = 0;
    queue<pair<int, int>> q;

    memset(chk, 0, sizeof(chk));

    for (int r = 0; r < N; r++)
    {
        for (int c = 0; c < N; c++)
        {
            if (!chk[r][c] && m[r][c] > lv)
            {
                ret++;
                q.push({ r, c });
                chk[r][c] = 1;

                while (!q.empty())
                {
                    int rr = q.front().first;
                    int cc = q.front().second;
                    q.pop();

                    for (int d = 0; d < 4; d++)
                    {
                        int nr = rr + dr[d];
                        int nc = cc + dc[d];

                        if (isVaild(nr, nc) && m[nr][nc] > lv)
                        {
                            q.push({ nr, nc });
                            chk[nr][nc] = 1;
                        }
                    }
                }
            }
        }
    }
    

    return ret;
}

int dfs()
{
    int ret = 0;
    for (int lv = 0; lv < M; lv++)
    {
        ret = max(bfs(lv), ret);
    }
    return ret;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N;
    for (int r = 0; r < N; r++)
    {
        for (int c = 0; c < N; c++)
        {
            cin >> m[r][c];
            if (m[r][c] > M)
                M = m[r][c];
        }
    }

    cout << dfs() << "\n";
}
  • 다른사람 풀이
#include<cstdio>
#include<algorithm>
using namespace std;
const int MXN = 100, fx[] = { 1,-1,0,0 }, fy[] = { 0,0,1,-1 };
int n, par[MXN*MXN],r,c,ck[MXN][MXN];
int f(int x) { return x - par[x] ? par[x] = f(par[x]) : x; }
pair<int, int> p[MXN*MXN];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n*n; i++) scanf("%d", &p[i].first), p[i].second = par[i]=i;
    sort(p, p + n*n);
    for (int i = n*n - 1; i >= 0; i--) {
        c++;
        ck[p[i].second / n][p[i].second%n] = 1;
        for (int j = 0; j < 4; j++) {
            int tx = p[i].second / n + fx[j], ty = p[i].second%n + fy[j],t=tx*n+ty;
            if (tx >= 0 && ty >= 0 && tx < n && ty < n && ck[tx][ty] && f(t) != f(p[i].second)) par[f(t)] = f(p[i].second),c--;
        }
        if (!i || p[i - 1].first != p[i].first) r = r>c ? r : c;
    }
    printf("%d", r);
    return 0;
}
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

constexpr int MXN = 100, fx[] = { 1,-1,0,0 }, fy[] = { 0,0,1,-1 };

int n, par[MXN * MXN], r, c, ck[MXN][MXN];
pair<int, int> p[MXN * MXN];

void printDt()
{
    int lim = n * n;

    for (int i = 0; i < lim;)
    {
        do
        {
            cout << par[i];
            cout << " ";
            i++;
        } while (i % n);

        cout << "\n";
    }

    for (int r = 0; r < n; r++)
    {
        for (int c = 0; c < n; c++)
            cout << ck[r][c];
        cout << "\n";
    }
}

// f(x) : par[x] == x -> return x 
// f(x) : par[x] != x -> return f(par[x]) 동시에 par[x] = f(par[x])로 바뀜
int f(int x)
{
    if (x == par[x])
    {
        return x;
    }
    else // x != par[x]
    {
        return par[x] = f(par[x]);
    }
    // return x - par[x] ? par[x] = f(par[x]) : x;
}

int main()
{
    scanf("%d", &n);

    for (int i = 0; i < n * n; i++)
    {
        scanf("%d", &p[i].first);
        p[i].second = par[i] = i;
    }

    sort(p, p + n * n);

    // 최고 높이 -> 낮은 높이 순환
    for (int i = n * n - 1; i >= 0; i--)
    {
        // 현재 높이의 섬의 갯수인가?
        c++;
        // 방문함을 기록
        ck[p[i].second / n][p[i].second % n] = 1;
        
        // 4가지 방향을 방문함
        for (int j = 0; j < 4; j++)
        {
            int tx = p[i].second / n + fx[j];
            int ty = p[i].second % n + fy[j];
            // 현 위치
            int t = tx * n + ty;
            
            // ck[tx][ty] == 1, 이미 방문했어야 함 (의미 : 현 위치 보다는 높거나 같은 위치이다)
            // f(t : 새위치) != f(p[i].second : 이전위치)
            if (tx >= 0 && ty >= 0 && tx < n && ty < n && ck[tx][ty] && f(t) != f(p[i].second))
            {
                // par[f(t)] : 새 위치의 par[f(t)]는 이전 위치의 f(p[i].second)로 바뀐다.(꼭대기 위치 값)
                par[f(t)] = f(p[i].second);
                // 새 위치는 이전에 방문한 곳 다시 말해 현 위치 보다 높은 곳
                // 병합 되므로 위치의 갯수를 줄인다.
                c--;
            }
        }

        if (!i || p[i - 1].first != p[i].first)
        {
            r = r > c ? r : c;
        }
    }
    
    // 결론 : 제일 높은 지대부터 물을 빼면서 섬의 갯수를 새는 방법

    printf("%d", r);

    return 0;
}

댓글남기기