프로그래밍 공부
작성일
2024. 2. 20. 23:56
작성자
WDmil
728x90

문제 설명

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

 

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

 

제한사항

 

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

입출력 예

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

문제 해설

문제 자체가 완전탐색형태로 도 풀 수 있는데 너무 복잡해지고, 시간을 초과해서 시간초과가 나타난다.

 

좀 꼼수를 부려야 하는데, 문제 유형의 규칙을 확인해보면 된다.

 

모든 차량은 들어온 지점과 나간 지점이 존재한다.

언제나 나간지점을 기준으로 체크하면된다

(그 외에 설치해도 확인은 가능하나, 나간지점이 가장 큰 위치에 설치하여도 똑같은 효과가 나타남)

 

즉, 카메라를 생각하면 늘 가능한 겹치는부분의 가장 큰 나간위치를 기준으로 카메라가 한개씩 증가한다고 생각하면 된다.


첫 번째 시도

#include <string>
#include <vector>
#include <list>

using namespace std;

bool Overlap(const vector<int>& a, const vector<int>& b) {
    return (max(a[0], b[0]) <= min(a[1], b[1]));
}

int solution(vector<vector<int>> routes) {
    int answer = 0;
    list<vector<int>> routes_L(routes.begin(), routes.end());
    
    while(routes_L.size() > 0)
    {
        vector<int> select(routes_L.front());
        routes_L.pop_front();
        answer++;
        
        for(auto def = routes_L.begin(); def != routes_L.end(); ) {
            if(Overlap(select, (*def)))
                def = routes_L.erase(def);
            else
                ++def;
        }
    }

    return answer;
}

실패

 

겹치는 여부를 확인하고, 겹치는 객체를 OVerlap기준으로 순환하면서, 전체순환중 겹치는 객체를 날리게 했다.

 

그랬더니, 그 모든 결과가 효율적으로 나타나지는 않는다는걸 알게됨.

가장 먼저 제거된 객체가 가장 효율적인 객체들이 아닐 수 있기 때문


두 번째 시도

#include <string>
#include <vector>
#include <list>
#include <map>


using namespace std;

bool Overlap(const vector<int>& a, const vector<int>& b) {
    return (max(a[0], b[0]) <= min(a[1], b[1]));
}

int solution(vector<vector<int>> routes) {
    int answer = 0;
    list<vector<int>> routes_L(routes.begin(), routes.end());

    while (routes_L.size() > 0)
    {
        answer++;
        map<int, vector<vector<int>>> line_search;
        for (auto& line_1 : routes_L) {
            vector<vector<int>> search;
            for (auto& line_2 : routes_L)
                if (Overlap(line_1, line_2)) 
                    search.push_back(line_2);
            line_search[search.size()] = search;

        }

        for (auto& def : line_search.rbegin()->second)
            routes_L.remove(def);

    }

    return answer;
}

실패

 

이번에는 map형태로 데이터를 정리하고, 가장 큰 객체값을 확인한다음에 해당하는 거리값을 전부 날려주는 형태로 함수를 구성했다.

 

그래도 실패했다.

겹치는경우가 가장 많은 수 를 기준으로 카메라를 묶어두어도, 이 결과가 가장 효율적이지 않을 수 있기 때문이다.


세 번쨰 시도

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

bool sorttwo(const vector<int>& a, const vector<int>& b) {
    return (a[0] < b[0]);
}

int solution(vector<vector<int>> routes) {
    sort(routes.begin(), routes.end(), sorttwo);
    int answer = 0;
    int chack = 300001;
    
    for(auto& def : routes) {
        if(chack <= def[0]) {
            chack = def[1];
        }
        else {
            chack = def[0];
            answer++;
        }
    }
    return answer;
}

실패

 

전 실패과정에서 뭐가 부족한지 생각해보니까. 아주 간단한 규칙을 깨달았다.

 

가능한. 묶을수 있는 수 중에서 나간 위치값을 기준으로 카메라를 배치하면 된다.

물론, 그 전에 sort를 해주어야 함을 분명하다.

 

그러나, 이러한 객체갱신 여부를 실수했다.


네 번째 시도

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

bool sorttwo(const vector<int>& a, const vector<int>& b) {
    return (a[1] < b[1]);
}

int solution(vector<vector<int>> routes) {
    int answer = 0;
    int chack = -30001;
    sort(routes.begin(), routes.end(), sorttwo);

    for (auto& def : routes) {
        if (def[0] > chack) {
            answer++;
            chack = def[1];
        }
    }

    return answer;
}

성공

이번에는 좀더 쉽게 생각하기로 했다.

 

그냥, 정렬해버리고 나간차량 기준으로 들어온 차가 나간차보다 더 클경우, 해당차량의 나간위치 기준으로 정리해주면된다.

728x90

'코딩테스트 문제 풀이 > 탐욕법' 카테고리의 다른 글

광물 캐기  (0) 2024.04.17
(2023 현대모비스 알고리즘 경진대회 예선)상담원 인원  (0) 2024.03.07
섬 연결하기  (0) 2024.02.15
구명 보트  (0) 2024.02.15
큰 수 만들기  (0) 2024.02.05