Codetree. 생명과학부 랩 인턴
1. 문제설명
n * m
크기의 격자판에 곰팡이 정보가 주어진다.- 곰팡이의 정보는
x, y, s, d, b
로 표현된다.- 각각은 (x, y)인 위치, 1초동안 움직이는 거리, 이동 방향, 곰팡이의 크기
- 첫번째 열부터 아래로 열 개수만큼 탐색 진행
i
번째 열에서 아래로 내려가며 가장 빨리 발견한 곰팡이를 채취한다.- 채취하고 나면 빈칸이 된다.
- 채취할 곰팡이가
i
번째 열에 없을 수도 있다.
- 남은 곰팡이가 입력으로 주어진 방향과 속력으로 이동한다.
- 만약 벽에 도달하면 방향을 반대로 바꾼다.
- 방향을 바꿀 때는 시간이 소모되지 않는다.
- 모든 곰팡이의 이동이 끝나고 같은 칸에 여러 개의 곰팡이가 존재할 수 있다.
- 이 때, 곰팡이의 크기
b
가 큰 녀석만 살아남는다.
- 이 때, 곰팡이의 크기
- 각 열에서의 탐색은 1초가 걸리며, 열 개수만큼만 탐색을 진행하고 종료한다.
-
모든 열을 검사했을 때, 채취한 곰팡이 크기의 총합을 구하라!
- 문제 분류
- Implementation, dx/dy,
2. 알고리즘 설계
- 문제의 내용을 그대로 구현해주면 되는데 헷갈릴 만한 포인트가 몇 가지 있었다.
- 가장 빨리 발견한 곰팡이를 채취할 때
- 어떤 조건도 없이 그냥 인덱스 위치가 가장 앞에 있는 걸 잡아먹는다.
- 같은 칸에 여러 개의 곰팡이가 존재할 때
- 크기가 같으면 어쩌나 고민했지만, 문제에 크기가 전부 다르다고 명시되어 있음.
- 벽을 만나면 방향이 정반대가 되는데,
- 바뀐 방향이 유지되어야 한다는 것!
- 위로 올라가다 벽을 만나면 방향이 아래로 바뀌게 되고
- 향후 시뮬레이션에서도 이 아래 방향으로 시작해야 한다!
- 언급된 점들만 주의하면, 문제없이 구현할 수 있었다.
3. 전체 코드
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
struct info {
int x, y, s, d, b;
};
const int dx[] = { 0,-1,1,0,0 };
const int dy[] = { 0,0,0,1,-1 };
int n, m, k, ans;
int A[105][105];
vector<info> v;
void collect(int x, int y) {
A[x][y] = 0;
for (int i = 0; i < v.size(); i++) {
if (v[i].x == x && v[i].y == y) {
v[i].x = -1;
v[i].y = -1;
ans += v[i].b;
break;
}
}
}
bool oom(int x, int y) { return x < 1 || y < 1 || x > n || y > m; }
void move() {
for (int i = 0; i < v.size(); i++) {
auto& nxt = v[i];
if (nxt.x == -1 && nxt.y == -1) continue;
int x = nxt.x, y = nxt.y;
int dir = nxt.d;
int s = nxt.s;
A[x][y]++;
while (s--) {
x += dx[dir];
y += dy[dir];
if (oom(x, y)) {
x -= dx[dir];
y -= dy[dir];
s++;
if (dx[dir] != 0)
dir = dx[dir] > 0 ? dir - 1 : dir + 1;
else if (dy[dir] != 0)
dir = dy[dir] > 0 ? dir + 1 : dir - 1;
}
}
v[i].x = x;
v[i].y = y;
v[i].d = dir;
A[x][y]--;
}
}
void eat() {
vector<info> tmp;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (A[i][j] < -1) {
tmp.push_back({ i,j,0,0,0 });
A[i][j] = -1;
}
for (auto& nxt : tmp) {
if (nxt.x == -1 && nxt.y == -1) continue;
vector<int> idx;
int mx = 0;
for (int i = 0; i < v.size(); i++) {
auto& cmp = v[i];
if (nxt.x == cmp.x && nxt.y == cmp.y) {
idx.push_back(i);
mx = max(mx, cmp.b);
}
}
for(int i : idx)
if (v[i].b < mx) {
v[i].x = -1;
v[i].y = -1;
}
}
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
cin >> n >> m >> k;
while (k--) {
int x, y, s, d, b;
cin >> x >> y >> s >> d >> b;
v.push_back({ x,y,s,d,b });
A[x][y] = -1;
}
for (int j = 1; j <= m; j++) {
for (int i = 1; i <= n; i++) {
if (A[i][j] == -1) {
collect(i, j);
break;
}
}
move();
eat();
}
cout << ans;
return 0;
}
4. 소감
- 잡아먹힌 곰팡이를 (-1,-1)로 처리하였다.
- 지울 벡터의 인덱스를 기억했다가 erase로 처리해도 좋았을 거 같다.
- 거의 모든 함수에서 모든 곰팡이를 탐색한다.
- 이거에 대한 효율성에 대해 고민한다면 시간을 조금 더 줄일 수 있을 거 같다.
- 내 코드 수행 시간은 451ms인데, 찾아보니 82ms로 해결한 사람도 있었다.