낚시왕 17143

PublicMinsu·2023년 9월 5일
0

문제

접근 방법

낚시왕의 이동 범위는 가로 크기이다.
즉 반복문으로 가로 크기만큼 돌면서 해당하는 가로 위치에서 가장 수면에 가까운 상어를 제거하면 된다.

상어는 각자 정해진 규칙에 따라 이동하면 된다.
가로, 세로로만 움직인다는 점을 주목하면 된다.
또 주목해야 할 점은 속력이다. 격자판 크기보다 속력이 크다는 점은 주의해야 한다. 원래 위치에 원래 방향으로 복구되는 속도는 계산 안 해주는 것이 이득이다. 그 값은 R 또는 C에 1을 빼고 2를 곱한 값이다.
나머지 연산을 해주어 불필요한 속력을 제거해 준다.

코드

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;
typedef tuple<int, int, int, int, int> shark; // 행, 열, 속력, 방향, 크기
int dy[] = {-1, 1, 0, 0}, dx[] = {0, 0, 1, -1}, R, C, M, ret;
vector<vector<int>> map;
vector<shark> sharks, buffer;
void input()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> R >> C >> M;
    map = vector<vector<int>>(R, vector<int>(C, -1));
    int r, c, s, d, z, twiceR = R - 1 << 1, twiceC = C - 1 << 1;
    while (M--)
    {
        cin >> r >> c >> s >> d >> z;
        --r, --c, --d;
        if (r == 0 && d == 0) // 위로 가려는 것
            d = 1;
        else if (r == R - 1 && d == 1)
            d = 0;
        else if (c == C - 1 && d == 2)
            d = 3;
        else if (c == 0 && d == 3)
            d = 2;
        if (d < 2) // 제자리로 가는 비용은 줄인다.
            s %= twiceR;
        else
            s %= twiceC;
        map[r][c] = buffer.size();
        buffer.push_back({r, c, s, d, z});
    }
}
void move()
{
    for (auto &m : map)
        fill(m.begin(), m.end(), -1);
    for (int i = 0; i < sharks.size(); ++i)
    {
        shark cur = sharks[i];
        int r = get<0>(cur);
        int c = get<1>(cur);
        int s = get<2>(cur);
        int d = get<3>(cur);
        int z = get<4>(cur);
        if (d < 2) // 위, 아래
        {
            for (int i = 0; i < s; ++i)
            {
                r += dy[d];
                if (r == 0)
                    d = 1;
                else if (r == R - 1)
                    d = 0;
            }
            get<0>(cur) = r;
        }
        else // 오른쪽, 왼쪽
        {
            for (int i = 0; i < s; ++i)
            {
                c += dx[d];
                if (c == 0)
                    d = 2;
                else if (c == C - 1)
                    d = 3;
            }
            get<1>(cur) = c;
        }
        get<3>(cur) = d;
        if (map[r][c] != -1) // 만약 해당 좌표에 이미 값이 존재한다면
        {
            shark next = buffer[map[r][c]];
            if (get<4>(next) > z) // 기존 상어의 값이 더 크다면 무시
                continue;
            get<2>(next) = s;
            get<3>(next) = d;
            get<4>(next) = z;
            buffer[map[r][c]] = next;
        }
        else // 해당 좌표에 값이 존재하지 않는다면
        {
            map[r][c] = buffer.size();
            buffer.push_back(cur);
        }
    }
}
void solve()
{
    for (int i = 0; i < C; ++i)
    {
        for (int j = 0; j < R; ++j)
            if (map[j][i] != -1)
            {
                int idx = map[j][i];
                ret += get<4>(buffer[idx]);
                buffer.erase(buffer.begin() + idx);
                break;
            }
        sharks.clear();
        sharks.swap(buffer);
        move();
    }
    cout << ret;
}
int main()
{
    input();
    solve();
    return 0;
}

풀이

범위를 넘어가는 경우에 대해서 반복문으로 해결했지만, 더 빠른 시간을 위해선 if문을 활용하여 해결해 주는 것이 좋다.
적어도 2번의 if문을 사용해서 값을 가공해 줘야 한다.
이미 한번 넘어간 뒤에 가공해 주는 과정에서 또 넘어갈 수 있기 때문이다. (오른쪽 끝에서 오른쪽으로 거의 2배에 해당하는 속력으로 간다고 생각하면 무슨 뜻인지 알 것이다)

profile
연락 : publicminsu@naver.com

0개의 댓글