오늘의 알고리즘

[C++] 백준 2933 미네랄

하늘하늘 . 2022. 7. 21. 21:34
 
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <queue>
 
bool bVisit[101][101] = {};
int iDirX[4] = { 1,-1,0,0 };
int iDirY[4] = { 0,0,1,-1 };
// 높이
int R = 0;
// 길이
int C = 0;
 
void Down(std::vector<std::string>& vec)
{
    int iMaxNumber = 1;
 
    for (int i = 0; i < R; ++i)
    {
        for (int j = 0; j < C; ++j)
        {
            if (bVisit[i][j])
                vec[i][j] = '.';
        }
    }
 
    while (true)
    {
        bool bCan = true;
        ++iMaxNumber;
 
        for (int i = 0; i < R; ++i)
        {
            for (int j = 0; j < C; ++j)
            {
                if (bVisit[i][j])
                {
                    if (i + iMaxNumber < vec.size())
                    {
                        if (vec[i + iMaxNumber][j] == 'x')
                        {
                            bCan = false;
                            break;
                        }
                    }
 
                    else
                    {
                        bCan = false;
 
                        break;
                    }
                }
 
            }
 
            if (!bCan)
                break;
        }
 
 
        if (bCan)
            continue;
 
        else
        {
            --iMaxNumber;
            break;
        }
    }
 
    for (int i = 0; i < R; ++i)
    {
        for (int j = 0; j < C; ++j)
        {
            if (bVisit[i][j])
                vec[i + iMaxNumber][j] = 'x';
        }
    }
 
    memset(bVisit, false, sizeof(bVisit));
}
 
// 바닥이랑 연결되어있는가 검색
bool Check(std::vector<std::string> vec, int iRow, int iCol)
{
    if (iRow < 0 || iRow >= vec.size() || iCol < 0 || iCol >= vec[iRow].size() ||
        vec[iRow][iCol] == '.' || bVisit[iRow][iCol])
        return false;
 
    bool bSubvisit[101][101] = {};
 
    int iFloor = vec.size() - 1;
    std::queue<std::pair<int, int>> que = {};
    que.push({ iRow, iCol });
    bSubvisit[iRow][iCol] = true;
 
    while (!que.empty())
    {
        int iX = que.front().first;
        int iY = que.front().second;
        que.pop();
 
        if (iX == iFloor)
            return false;
 
        for (int i = 0; i < 4; ++i)
        {
            int iNextX = iX + iDirX[i];
            int iNextY = iY + iDirY[i];
 
            if (iNextX >= 0 && iNextX < vec.size() &&
                iNextY >= 0 && iNextY < vec[0].size())
            {
                if (!bSubvisit[iNextX][iNextY] && vec[iNextX][iNextY] == 'x')
                {
                    bSubvisit[iNextX][iNextY] = true;
                    que.push({ iNextX, iNextY });
                }
            }
        }
    }
 
    for (int i = 0; i < vec.size(); ++i)
    {
        for (int j = 0; j < vec[i].size(); ++j)
        {
            if (bSubvisit[i][j])
                bVisit[i][j] = true;
        }
    }
 
    return true;
}
 
int main()
{
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
    std::cin >> R >> C;
    std::vector<std::string> vec(R, "");
 
    for (int i = 0; i < R; ++i)
    {
        std::cin >> vec[i];
    }
 
    int N = 0;
    std::cin >> N;
 
    bool bLeft = true;
 
    for (int i = 0; i < N; ++i)
    {
        bool bCheck = false;
        int iHeight = -1;
        int iBreak = -1;
        std::cin >> iHeight;
 
        if (bLeft)
        {
            for (int j = 0; j < C; ++j)
            {
                if (vec[R - iHeight][j] == 'x')
                {
                    vec[R - iHeight][j] = '.';
                    iBreak = j;
                    break;
                }
            }
        }
 
        else
        {
            for (int j = C - 1; j >= 0; --j)
            {
                if (vec[R - iHeight][j] == 'x')
                {
                    vec[R - iHeight][j] = '.';
                    iBreak = j;
                    break;
                }
            }
        }
 
        if (iBreak != -1)
        {
            if (Check(vec, R - iHeight - 1, iBreak))
                bCheck = true;
 
            if (bLeft)
            {
                if (Check(vec, R - iHeight, iBreak + 1))
                    bCheck = true;
            }
 
            else
            {
                if (Check(vec, R - iHeight, iBreak - 1))
                    bCheck = true;
            }
 
            if (Check(vec, R - iHeight + 1, iBreak))
                bCheck = true;
        }
 
        if (bCheck)
            Down(vec);
 
        bLeft = !bLeft;
    }
 
    for (int i = 0; i < R; ++i)
    {
        std::cout << vec[i];
 
        if (i != R -1)
            std::cout << "\n";
    }
 
    return 0;
}
 

구현에 진짜 애를 먹었습니다.

여러가지를 생각했어야 했는데 단면만 보고 풀어서...

처음에는 던지는 방향 한개와 그 위만 검색했는데 아래도 떨어질 수 있다는 걸 판단못했고

두번째로는 밑바닥만 붙으면 되겠지라는 생각으로 풀었더니 위에서 걸렸다면 더 떨어지지 못한다라는 생각을 못했습니다...

생각을 좀 오래했어야 했었네요.