[프로그래머스] PS/Java
[lv2/pccp 기출 3번] 충돌위험 찾기 - JAVA
SH3542
2025. 4. 24. 16:28
https://school.programmers.co.kr/learn/courses/30/lessons/340211
이게 왜 2레벨인지 진짜 모름
어려웠던 요인
1. 거쳐가야 할 포인트 수가 가변적이다.
2. 로봇의 도착 시점은 제각각이다. (도착 표시 따로하고, 도착한건 이동 로직 미포함 해야 함)
3. 도착과 맵 밖으로 나감이 따로 존재하고, 시작과 최초 도착시에도 충돌 체크를 해야 한다.
풀이
1. 로봇이 거쳐가야 할 포인트를 실제 좌표로 바꿔놓는다. = move[]
2. while 루프를 돌며,
2-1. 충돌 체크
충돌 체크는 로봇의 시작지점(0초인 경우)에서도 이뤄져야 하기 때문에, 이동 동작보다 먼저 한다.
2차원 배열로 하면, 매 순간 100*100 크기를 선언해야 해서
map에 key = r + " " + c로 비교했다.
더 좋은 방법이 있을 것 같은데, 일단 로봇 최대 100개라 나쁘진 않은 방법 같다.
2-2. 종료조건 판별
모든 로봇이 거쳐간 포인트 수가 전체 포인트 수와 같으면 종료한다.
여기서 판별해야, 처음부터 다 도착해있는 경우(= 모든 로봇의 포인트가 1개)나, 전부 도착한 이후에도 한 번은 비교해야 함을 만족할 수 있다.
2-3. 최단거리 이동
r이동이 c이동보다 우선 되어야한다.
벽같은 진로방해 요소가 없으므로 단순히 좌표 차이에 따라 r-- or r++ 해준다.
목표지점에 도달했다면 거쳐간 포인트 수를 올리고 다음 포인트의 인덱스를 가리킨다.
import java.util.*;
class Solution {
static class Pos {
int r, c;
Pos(int r, int c) {
this.r = r;
this.c = c;
}
}
public int solution(int[][] points, int[][] routes) {
int answer = 0;
int P = points.length;
int R = routes.length;
int RL = routes[0].length;
int RT = R * RL;
int rCnt = R;
// 로봇 별 이동 경로
Pos[][] move = new Pos[R][RL];
// 로봇 별 현재 위치
Pos[] now = new Pos[R];
// 로봇 별 거쳐간 포인트 목록
int[] idx = new int[R];
// 물류 센터를 벗어났는지 여부 (도착과 구분해야 함)
boolean[] out = new boolean[R];
for (int i=0; i<R; i++) {
int[] route = routes[i];
for(int j=0; j<RL; j++) {
int p = route[j] - 1; // 0-indexed : 1번 포인터는 0번 idx에 위치
move[i][j] = new Pos(points[p][0], points[p][1]);
if(j == 0) {
now[i] = new Pos(points[p][0], points[p][1]);
}
}
}
while(true) {
Map<String, Integer> check = new HashMap<>();
for(int i=0; i<R; i++) {
if(out[i]) continue;
int r = now[i].r;
int c = now[i].c;
String key = new String(r +" " + c);
check.merge(key, 1, (ov, nv) -> ov + 1);
// 나간 상태는 아니나 목적지에 도달한 경우, 한 번 충돌체크하고 나감 처리
if(!out[i] && (idx[i] == RL - 1)) {
out[i] = true;
}
}
// 충돌 => 로봇이 2개 이상 위치하는 경우
for(int v : check.values()) {
if(v > 1) answer++;
}
if(rCnt == RT) break;
// 로봇 이동
for(int i=0; i<R; i++) {
// 마지막 포인트에 있는 상태
if(idx[i] == RL - 1) continue;
int r = now[i].r;
int c = now[i].c;
// 다음 포인트 좌표
int gr = move[i][idx[i] + 1].r;
int gc = move[i][idx[i] + 1].c;
if(r > gr) {
r--;
}
else if(r < gr) {
r++;
}
// r == gr
else if(c > gc) {
c--;
}
else {
c++;
}
if(r == gr && c == gc) {
idx[i]++;
rCnt++;
}
now[i].r = r;
now[i].c = c;
}
}
return answer;
}
}