알고리즘 - 충돌위험 찾기
🚚 운송 로봇 충돌 문제 — 해결 여정 정리
이 문서는 첫 번째 구현부터 최종 정답까지 어떤 이유로 오답이 발생했고,
어떤 식으로 문제를 해결해 갔는지를 단계별로 정리한 기록이다.
1. ✅ 첫 번째 구현의 설계 방식
초기 구현의 핵심 논리는 다음과 같았다.
✔ 구현 아이디어
-
각 로봇이 이동하는 모든 지점을
movebot()으로 계산해 리스트에 담는다. -
zip_longest(*paths)로 시간 t에 로봇들이 있는 좌표를 동시에 비교한다. -
시간이 같고 좌표가 같은 경우 충돌 카운트 증가.
✔ movebot()이 생성하는 데이터 형태
출발점 → 도착점까지 X → Y 순으로 이동 경로 좌표를 차례대로 리스트로 구성.
2. ❌ 초기 구현이 틀렸던 이유
실제로 제출하면 몇몇 케이스에서만 오답이 나왔다.
주요 원인을 정리하면 다음과 같다.
문제 1. 로봇별 “전체 시간 경로”가 아니라 “구간별 경로”를 저장함
초기 코드:
moveArr.append(r)여기서 moveArr는 다음 형태가 됨:
[ r1_구간1, r1_구간2, r2_구간1, r3_구간1, ... ]
즉,
-
로봇 1의 전체 경로가 아니라
-
로봇 1의 구간별 경로가 따로따로 저장되고
-
로봇 2, 로봇 3의 구간 경로가 섞여 들어감
그다음 zip_longest(*moveArr)을 돌리면:
t=0 → r1_구간1[0], r1_구간2[0], r2_구간1[0], ...
t=1 → r1_구간1[1], r1_구간2[1], ...
즉, 시간축 자체가 깨짐
전혀 다른 시간의 좌표들을 "같은 시간"처럼 비교하게 되어 충돌 계산이 틀어짐.
문제 2. 충돌 횟수 계산 방식 오류
초기 구현:
if strx[str(y)] > 1:
result += 1이 방식은 아래처럼 잘못된 값을 만든다.
- 같은 시각 같은 좌표에 로봇 3대가 모이면
→ count = 1, 2, 3
→ 2일 때 +1
→ 3일 때 또 +1
→ 실제로는 1회여야 하는데 2회 증가
즉, 중복 충돌이 과다 계산됨.
정답 규칙은
하나의 좌표에 두 대 이상 모이면 '1'번만 증가한다.
따라서 “1 → 2”가 되는 순간만 세야 한다.
문제 3. 출발 시점(t=0) 충돌 누락
문제에서는:
로봇은 모두 0초에 동시에 출발한다.
출발 좌표도 충돌 가능성이 있음.
하지만 초기 구현에서는 t=0의 출발 좌표를 날짜에 넣지 않아서
시작점에서 로봇들이 같은 포인트에 있을 경우의 충돌을 누락했다.
문제 4. movebot()의 이동 경로 계산 오류
초기의 movebot에서는 다음 문제가 있었다.
-
X축 이동 + Y축 이동 순서가 불안정하게 갱신됨
-
업데이트된 x,y를 유지하지 않고 잘못된 좌표를 찍는 케이스가 있었음
(특정 테스트에서 불일치 → 충돌이 누락됨)
3. 🔧 주요 수정 단계
3-1. 로봇별 전체 경로 배열 생성
기존: moveArr = [구간1, 구간2, ...]
→ 변경: paths = [로봇1_전체경로, 로봇2_전체경로, ...]
이렇게 모든 로봇의 경로를 하나로 이어붙여서 정확한 시간 축을 맞춤.
3-2. t=0 출발 좌표 포함
x0, y0 = points[start - 1]
path.append((x0, y0))이제 출발 순간 충돌까지 모두 계산됨.
3-3. 충돌 카운트 방식 보정
잘못된 방식:
if count > 1:
result += 1올바른 방식:
if count == 2:
result += 1즉, "1 → 2"로 증가할 때만 1회 카운트.
3-4. movebot() 올바르게 재구현
다음 규칙을 정확히 반영:
-
r(x) 먼저 이동
-
그다음 c(y) 이동
-
이동할 때마다 한 칸씩 path 기록
4. 🎯 최종 정답 코드
아래는 모든 오류를 고쳐 완성된 정답 코드.
from itertools import zip_longest
def movebot(x1, y1, x2, y2):
path = []
x, y = x1, y1
# r 좌표(x) 먼저 이동
if x1 != x2:
d = 1 if x2 > x1 else -1
for nx in range(x1 + d, x2 + d, d):
x = nx
path.append((x, y))
# 그 다음 c 좌표(y) 이동
if y1 != y2:
d = 1 if y2 > y1 else -1
for ny in range(y1 + d, y2 + d, d):
y = ny
path.append((x, y))
return path
def solution(points, routes):
paths = []
for route in routes:
path = []
start = route[0]
x0, y0 = points[start - 1]
path.append((x0, y0))
for i in range(len(route) - 1):
s = route[i]
e = route[i + 1]
x1, y1 = points[s - 1]
x2, y2 = points[e - 1]
seg = movebot(x1, y1, x2, y2)
path.extend(seg)
paths.append(path)
result = 0
for step in zip_longest(*paths, fillvalue=None):
counter = {}
for pos in step:
if pos is None:
continue
if pos in counter:
counter[pos] += 1
if counter[pos] == 2:
result += 1
else:
counter[pos] = 1
return result5. 🎉 요약 – 최종 완성까지의 핵심 변화
| 단계 | 문제점 | 해결 |
|---|---|---|
| 1 | 구간별 경로 저장 → 시간축 틀어짐 | 로봇별 전체 경로 리스트로 변경 |
| 2 | t=0 시작 충돌 누락 | 출발 좌표 삽입 |
| 3 | 충돌 3대 이상일 때 중복 카운트 | “1→2” 변화 시 1회만 증가 |
| 4 | 이동 경로 생성 오류 | X → Y 순서로 정확한 좌표 생성 |
| 5 | zip_longest 로 올바른 시간축 비교 | 정상적인 충돌 계산 가능 |
댓글
첫 번째 댓글을 남겨보세요.