PGMS_PCCP 3번_충돌위험 찾기 (Java)
[level 2] [PCCP 기출문제] 3번 / 충돌위험 찾기 - 340211
성능 요약
메모리: 183 MB, 시간: 195.24 ms
구분
코딩테스트 연습 > PCCP 기출문제
채점결과
정확성: 100.0
합계: 100.0 / 100.0
제출 일자
2025년 01월 28일 06:38:38
문제 설명
어떤 물류 센터는 로봇을 이용한 자동 운송 시스템을 운영합니다. 운송 시스템이 작동하는 규칙은 다음과 같습니다.
- 물류 센터에는 (r, c)와 같이 2차원 좌표로 나타낼 수 있는
n
개의 포인트가 존재합니다. 각 포인트는 1~n
까지의 서로 다른 번호를 가집니다. - 로봇마다 정해진 운송 경로가 존재합니다. 운송 경로는
m
개의 포인트로 구성되고 로봇은 첫 포인트에서 시작해 할당된 포인트를 순서대로 방문합니다. - 운송 시스템에 사용되는 로봇은
x
대이고, 모든 로봇은 0초에 동시에 출발합니다. 로봇은 1초마다 r 좌표와 c 좌표 중 하나가 1만큼 감소하거나 증가한 좌표로 이동할 수 있습니다. - 다음 포인트로 이동할 때는 항상 최단 경로로 이동하며 최단 경로가 여러 가지일 경우, r 좌표가 변하는 이동을 c 좌표가 변하는 이동보다 먼저 합니다.
- 마지막 포인트에 도착한 로봇은 운송을 마치고 물류 센터를 벗어납니다. 로봇이 물류 센터를 벗어나는 경로는 고려하지 않습니다.
이동 중 같은 좌표에 로봇이 2대 이상 모인다면 충돌할 가능성이 있는 위험 상황으로 판단합니다. 관리자인 당신은 현재 설정대로 로봇이 움직일 때 위험한 상황이 총 몇 번 일어나는지 알고 싶습니다. 만약 어떤 시간에 여러 좌표에서 위험 상황이 발생한다면 그 횟수를 모두 더합니다.
운송 포인트 n
개의 좌표를 담은 2차원 정수 배열 points
와 로봇 x
대의 운송 경로를 담은 2차원 정수 배열 routes
가 매개변수로 주어집니다. 이때 모든 로봇이 운송을 마칠 때까지 발생하는 위험한 상황의 횟수를 return 하도록 solution 함수를 완성해 주세요.
제한사항
- 2 ≤
points
의 길이 =n
≤ 100points[i]
는i + 1
번 포인트의 [r 좌표
,c 좌표
]를 나타내는 길이가 2인 정수 배열입니다.- 1 ≤
r
≤ 100 - 1 ≤
c
≤ 100 - 같은 좌표에 여러 포인트가 존재하는 입력은 주어지지 않습니다.
- 2 ≤
routes
의 길이 = 로봇의 수 =x
≤ 100- 2 ≤
routes[i]
의 길이 =m
≤ 100 routes[i]
는i + 1
번째 로봇의 운송경로를 나타냅니다.routes[i]
의 길이는 모두 같습니다.routes[i][j]
는i + 1
번째 로봇이j + 1
번째로 방문하는 포인트 번호를 나타냅니다.- 같은 포인트를 연속으로 방문하는 입력은 주어지지 않습니다.
- 1 ≤
routes[i][j]
≤n
- 2 ≤
입출력 예
points | routes | result |
---|---|---|
[[3, 2], [6, 4], [4, 7], [1, 4]] | [[4, 2], [1, 3], [2, 4]] | 1 |
[[3, 2], [6, 4], [4, 7], [1, 4]] | [[4, 2], [1, 3], [4, 2], [4, 3]] | 9 |
[[2, 2], [2, 3], [2, 7], [6, 6], [5, 2]] | [[2, 3, 4, 5], [1, 3, 4, 5]] | 0 |
입출력 예 설명
입출력 예 #1
그림처럼 로봇들이 움직입니다. 3초가 지났을 때 1번 로봇과 2번 로봇이 (4, 4)에서 충돌할 위험이 있습니다. 따라서 1을 return 해야 합니다.
입출력 예 #2
그림처럼 로봇들이 움직입니다. 1, 3, 4번 로봇의 경로가 같아 이동하는 0 ~ 2초 내내 충돌 위험이 존재합니다. 3초에는 1, 2, 3, 4번 로봇이 모두 (4, 4)를 지나지만 위험 상황은 한 번만 발생합니다.
4 ~ 5초에는 1, 3번과 2, 4번 로봇의 경로가 각각 같아 위험 상황이 매 초 2번씩 발생합니다. 6초에 2, 4번 로봇의 충돌 위험이 발생합니다. 따라서 9를 return 해야 합니다.
입출력 예 #3
그림처럼 로봇들이 움직입니다. 두 로봇의 경로는 같지만 한 칸 간격으로 움직이고 2번 로봇이 5번 포인트에 도착할 때 1번 로봇은 운송을 완료하고 센터를 벗어나 충돌 위험이 없습니다. 따라서 0을 return 해야 합니다.
출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
문제 풀이
구현 문제이므로 코드에 자세한 주석을 작성해놓겠다. 자료구조나 구현 방법을 위주로 보면 도움이 될 것이다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.util.*;
class Solution {
class Robot{
int r, c;
boolean isEnd;
public Robot(int r, int c, boolean isEnd){
this.r = r;
this.c = c;
this.isEnd = isEnd;
}
}
static int hitCnt=0;
static int[] routeIdx;
static Robot[] robot;
static Map<Integer, List<Integer>> robotList; // r*100 + c, 로봇번호
public int solution(int[][] points, int[][] routes) {
robot = new Robot[routes.length];
routeIdx = new int[routes.length]; // 다음 목적지 가리키는 Idx, 0 ~ routes[0].length-1 임
// 시작점
for(int i=0; i<routes.length; i++){
robot[i] = new Robot(points[routes[i][0]-1][0], points[routes[i][0]-1][1], false);
}
Arrays.fill(routeIdx, 1);
//시작점도 같이 시작하면 충돌카운트 해줘야함
robotList = new HashMap<>();
for(int i = 0; i < routes.length; i++) {
makeRobotList(i);
}
hitCount();
while(true){
robotList = new HashMap<>();
for(int i=0; i<routes.length; i++){
if(robot[i].isEnd) continue;
int currPointIdx = routes[i][routeIdx[i]-1] - 1;
int[] currPoint = points[currPointIdx];
int nextPointIdx = routes[i][routeIdx[i]] - 1;
int[] nextPoint = points[nextPointIdx];
move(currPoint, nextPoint, robot[i]);
// 이동칸을 robotList에 기록
makeRobotList(i);
// 다음포인트 도착체크
checkNextPointArrival(i, nextPoint, routes);
}
// 충돌카운트
hitCount();
boolean flag = true;
for(Robot r : robot){
if(!r.isEnd){
flag = false;
break;
}
}
if(flag) break;
}
return hitCnt;
}
void move(int[] start, int[] next, Robot robot){
if(robot.r != next[0]) robot.r += (robot.r > next[0]) ? -1 : 1;
else if(robot.r == next[0] && robot.c != next[1]) robot.c += (robot.c > next[1]) ? -1 : 1;
}
void makeRobotList(int i){
int pos = robot[i].r * 100 + robot[i].c;
if(!robotList.containsKey(pos)) robotList.put(pos, new ArrayList<>());
robotList.get(pos).add(i);
}
void checkNextPointArrival(int i, int[] nextPoint ,int[][] routes){
if(robot[i].r == nextPoint[0] && robot[i].c == nextPoint[1]){
routeIdx[i]++;
if(routeIdx[i] >= routes[i].length) robot[i].isEnd = true;
}
}
void hitCount(){
for(List<Integer> rList : robotList.values()){
if(rList.size() >= 2) hitCnt++;
}
}
}