Programmers

[프로그래머스] 단속 카메라 / Python

개발하는 사막여우 2021. 1. 29. 12:55
반응형

문제주소 :programmers.co.kr/learn/courses/30/lessons/42884

 

코딩테스트 연습 - 단속카메라

[[-20,15], [-14,-5], [-18,-13], [-5,-3]] 2

programmers.co.kr


<문제 설명>

더보기

문제 설명

고속도로를 이동하는 모든 차량이 고속도로를 이용하면서 단속용 카메라를 한 번은 만나도록 카메라를 설치하려고 합니다.

고속도로를 이동하는 차량의 경로 routes가 매개변수로 주어질 때, 모든 차량이 한 번은 단속용 카메라를 만나도록 하려면 최소 몇 대의 카메라를 설치해야 하는지를 return 하도록 solution 함수를 완성하세요.

제한사항

  • 차량의 대수는 1대 이상 10,000대 이하입니다.
  • routes에는 차량의 이동 경로가 포함되어 있으며 routes[i][0]에는 i번째 차량이 고속도로에 진입한 지점, routes[i][1]에는 i번째 차량이 고속도로에서 나간 지점이 적혀 있습니다.
  • 차량의 진입/진출 지점에 카메라가 설치되어 있어도 카메라를 만난것으로 간주합니다.
  • 차량의 진입 지점, 진출 지점은 -30,000 이상 30,000 이하입니다.

입출력 예

routesreturn
[[-20,15], [-14,-5], [-18,-13], [-5,-3]] 2

입출력 예 설명

-5 지점에 카메라를 설치하면 두 번째, 네 번째 차량이 카메라를 만납니다.

-15 지점에 카메라를 설치하면 첫 번째, 세 번째 차량이 카메라를 만납니다.

 

<풀이법>

▒ 한줄 개념: 탐욕법 ▒ 

탐욕법을 통해 푸는 문제입니다.

문제에 주어진 [[-20,15], [-14,-5], [-18,-13], [-5,-3]] 의 예제를 그래프로 그려보면 다음과 같습니다.

이 상황에서 모든 차량을 한번씩 찍을 수 있도록 단속카메라가 들어가야하는 최소 위치를 확인해보면, 다음과 같습니다.

다음과 같습니다. 여기서 각 단속구간의 특징을 알 수 있는데, 바로 겹치는 부분들을 뽑아내는 것입니다.

앞에서부터 겹치는 부분들을 하나씩 뽑아내기 때문에, 탐욕법 알고리즘을 사용하여 문제를 풀게됩니다.

 

이 문제를 해결하는 알고리즘은 다음과 같습니다.

 

  1. routes의 각 원소([-20,15], [-14,-5],...)를 '시작점(s)'과 '끝점(e)'으로 쪼갠다.
    • ex : [-20,15] -> (-20, '0'(차량의 인덱스), 's'), (15, '0', 'e')
    • ex : [-14,-5] -> (-14, '1', 's'), (-5, '1', 'e')
  2. 각 쪼개진 점들의 배열을 정렬한다.
    • 정렬에서 key = 시간값 우선(-20,-14...), 시작/종료 값 차선('s' 가 'e'보다 앞)
  3. 정렬된 점들의 배열에서 다음의 조건들을 따져서 answer의 값을 구한다.
    • 만약 여태 지나간(이미 체크됨) 차량들이 전체 차량의 수와 같으면 break
    • 인덱스를 확인하여(a[1]) 이미 체크된 차량일 경우 다시 확인할 필요 없으니 continue
    • 만약 's'가 나타날 경우(어떤 차량의 시작점일 경우) 
      • '현재 체크 중인 차량들'현재 차량 인덱스 append
    • 만약 'e'가 나타날 경우(어떤 차량의 마지막점일 경우) 
      • '현재 체크 중인 차량들'을 전부 '이미 체크됨'에 넣음.
      • 현재 지점이 단속 카메라를 설치할 지점이므로 answer += 1

 

 

<코드(Python)>

def solution(routes):
    answer = 0
    all_t = []
    for r in range(len(routes)):
        all_t.append((routes[r][0], r, 's'))
        all_t.append((routes[r][1], r, 'e'))
    all_t.sort(key = lambda x:(x[0], -ord(x[2])))

    checked = []
    in_range = []
    for a in all_t:
        if len(checked) == len(routes):
            break
        if a[1] in checked:
            continue
        if a[-1] == 's':
            in_range.append(a[1])
        elif a[-1] == 'e' and len(in_range) != 0:
            checked += in_range
            in_range = []
            answer += 1

    return answer

 

 

더 많은 코드 보기(GitHub) : github.com/dwkim-97/CodingTest

 

 

반응형