낚시왕의 이동 범위는 가로 크기이다.
즉 반복문으로 가로 크기만큼 돌면서 해당하는 가로 위치에서 가장 수면에 가까운 상어를 제거하면 된다.
상어는 각자 정해진 규칙에 따라 이동하면 된다.
가로, 세로로만 움직인다는 점을 주목하면 된다.
또 주목해야 할 점은 속력이다. 격자판 크기보다 속력이 크다는 점은 주의해야 한다. 원래 위치에 원래 방향으로 복구되는 속도는 계산 안 해주는 것이 이득이다. 그 값은 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배에 해당하는 속력으로 간다고 생각하면 무슨 뜻인지 알 것이다)