Codetree. 전투 로봇
1. 문제설명
n * n
개의 격자에m
개의 몬스터와 하나의 전투로봇이 주어진다.- 한칸에는 몬스터가 하나 이상
- 전투로봇과 몬스터 모두 자연수 레벨을 가진다.
- 초기 전투로봇의 레벨은 2
- 전투로봇은 1차에 상하좌우로 인접한 한칸씩 이동할 수 있다.
- 자신의 레벨보다 큰 몬스터가 있는 칸은 지나칠 수 없고, 나머지는 지날 수 있다.
- 자신보다 레벨이 적은 몬스터만 없앨 수 있다.
- 이동할지 정하는 규칙
- 없앨 수 있는 몬스터가 있다면 없애러 간다.
- 없앨 수 있는 몬스터가 하나 이상이라면, 거리가 가장 가까운 몬스터를 없앤다.
- 거리는 해당 칸으로 이동할 때 지나야 하는 칸의 개수 의미
- 거리가 같은 몬스터가 여러개 있다면 상단/좌측의 순으로 우선순위가 부여된다.
- 없앨 몬스터가 없다면 종료
-
전투로봇은 본인의 레벨과 같은 수의 몬스터를 없앨 때마다 레벨 상승
- 문제 분류
- Implementation, Simulation, BFS
2. 알고리즘 설계
- 크게 3가지로 분할 구현하였다.
- 전투로봇과 몬스터의 거리 구하기, 없앨 몬스터 찾기, 몬스터 없애기
- 자신의 레벨과 같은 수의 몬스터를 없애면 레벨업을 하기 때문에
robot_exp
라는 변수로 관리해주었다. - 없앨 몬스터 찾기
- 현재 전투로봇의 위치와 살아남은 몬스터 간 거리를 구하고, 위치와 거리를 전부 벡터에 담는다.
- 거리/상단/좌측 순으로 정렬 기준을 세워 정렬한다.
- 정렬된 벡터의 첫번째 원소가 타겟이 된다.
- 만약, 벡터의 크기가 0이라면 타겟 몬스터가 없다는 의미 (종료조건)
- 거리 구하기
- 단순하게
|x2-x1| + |y2-y1|
로 구하면 안된다. - 레벨이 전투로봇보다 이하인 몬스터만 지나칠 수 있다.
- BFS를 통해 최단 경로를 명시해주어야 한다.
- 단순하게
- 몬스터 없애기
- 앞서 타겟을 찾았다면, 몬스터에 해당하는 위치의 값을 0으로 만든다.
- 로봇과 타겟의 위치의 값(0)을 서로
swap
한다. - 로봇의 위치를 타겟의 위치로 변경한다.
- 타겟의 위치는
{-1, -1}
로 변경하여 앞의 없앨 몬스터 찾기에서 바로continue
되도록 한다. - 몬스터를 잡아먹었다면
robot_exp++
를 해준다.- 만약
robot_exp
와 로봇의 레벨이 같아지면 로봇의 위치의 값을++
하면 된다.
- 만약
3. 전체 코드
4. 소감
- 문제에 있는 것을 정말 그대로 구현하면 되는 문제였다.
- 다만 전투로봇 레벨 이하의 몬스터를 지나칠 수 있다는 점에 주의한다.
- 레벨이 같다면 지나칠 수 있지만, 잡아먹을 수는 없다.
- 참조자와 속도의 관계
- 내 코드를 보면 몬스터 정보 및 그 외 정보들을 벡터에 담아 관리하였다.
- 벡터를 참조자가 아닌 형태로 사용했을 때와 참조자로 사용했을 때의 속도 차이가 분명했다.
auto nxt = monster[i]
와auto& nxt = monster[i]
는 각각 489ms, 290ms를 기록했다.- 참조자를 사용하는 습관을 가질 필요성을 느꼈다.