문제
1247 [S/W 문제해결 응용] 3일차 - 최적 경로
풀이
1. 초기접근
문제조건 해석
N <= 10 으로, 매우작음.
모든 경우를 체계적으로 따질 수 있으면 정답을 맞출 수 있다.
=> 모든 경우를 다 해보는 방법을 고려해보자.
가장 직관적인 방법은, 각 포인트의 거리들을 미리 구하고, 순열로 생성하며 모든 경우의 수를 탐색하는 것이다.
알고리즘
- 각 포인트들의 좌표를 가지고 만들 수 있는 모든 순열을 탐색해보며, 각 경우에서의 거리를 구해 최소 거리를 갱신.
- 순열을 만드는 방법은 파이썬 내장 함수인,
itertools.permutations()
로 손쉽게 구현
코드
import itertools
t = int(input())
for tc in range(1, t+1):
n = int(input())
l = list(map(int, input().split()))
# 회사, 집, 그리고 각 포인트들을 구분하여, 각 좌표를 튜플로, 저장.
company = (l[0], l[1])
home = (l[2], l[3])
points_sliced = l[4:]
points = []
for i in range(0, len(points_sliced), 2):
points.append((points_sliced[i], points_sliced[i+1]))
# 포인트들의 경로를 순열을 이용하여 모드 경우의 수를 탐색.
min_distance = float('inf')
for i in itertools.permutations(points):
# 각 경로 시작과 끝에 뒤에 회사와 집의 좌표를 넣어줌.
path = [company, *list(i), home]
# path 는 예를 들어 아래와 같은 꼴임.
# path = [(0, 0), (70, 70), (30, 30), (10, 10), (90, 90), (50, 50), (100, 100)]
# 각 경로에서의 걸리는 거리를 구함.
distance = 0
for idx in range(0, len(path)-1):
#distance += sum([abs(b-a) for a, b in zip(path[idx-1], path[idx])])
distance += abs(path[idx][0] - path[idx+1][0]) + abs(path[idx][1]-path[idx+1][1])
min_distance = distance if distance < min_distance else min_distance
print("#%d %d" %(tc, min_distance))
2. 유의할 점
for i in itertools.permutations(points)
에서 i 는 튜플임.
즉,i = ( (0, 0), (70, 70), (30, 30), (10, 10), (90, 90), (50, 50), (100, 100) )
와 같은 꼴임.- 따라서,
*list(i)
와 같이 list로 만든 뒤, unpacking 해줘야 함.
- 따라서,
- 주석처리한
distance += sum([abs(b-a) for a, b in zip(path[idx-1], path[idx])])
부분과 같이 써도 되지만, 좀 더 직관적인 코드로 적고자,distance += abs(path[idx][0] - path[idx+1][0]) + abs(path[idx][1]-path[idx+1][1])
을 사용. - 이 코드는 별로 파이썬스럽지 않아서 조금 아쉬움…
참고
Youth-tory 유스토리 님 블로그.
'취업과 기본기 튼튼 > 코딩 테스트 노트' 카테고리의 다른 글
[BOJ] 9466. 텀 프로젝트 (0) | 2019.04.07 |
---|---|
[BOJ] 1405. 미친로봇 (0) | 2019.04.04 |
[BOJ] 14888. 연산자 끼워넣기 (0) | 2019.04.02 |
파이썬으로 문제 풀 때 주의해야할 점들 (5) | 2019.03.26 |
[BOJ] 적록색맹 (0) | 2019.03.22 |