728x90
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

[문제 설명]

N개의 마을로 이루어진 나라가 있습니다. 이 나라의 각 마을에는 1부터 N까지의 번호가 각각 하나씩 부여되어 있습니다. 각 마을은 양방향으로 통행할 수 있는 도로로 연결되어 있는데, 서로 다른 마을 간에 이동할 때는 이 도로를 지나야 합니다. 도로를 지날 때 걸리는 시간은 도로별로 다릅니다. 현재 1번 마을에 있는 음식점에서 각 마을로 음식 배달을 하려고 합니다. 각 마을로부터 음식 주문을 받으려고 하는데, N개의 마을 중에서 K 시간 이하로 배달이 가능한 마을에서만 주문을 받으려고 합니다. 다음은 N = 5, K = 3인 경우의 예시입니다.

위 그림에서 1번 마을에 있는 음식점은 [1, 2, 4, 5] 번 마을까지는 3 이하의 시간에 배달할 수 있습니다. 그러나 3번 마을까지는 3시간 이내로 배달할 수 있는 경로가 없으므로 3번 마을에서는 주문을 받지 않습니다. 따라서 1번 마을에 있는 음식점이 배달 주문을 받을 수 있는 마을은 4개가 됩니다.
마을의 개수 N, 각 마을을 연결하는 도로의 정보 road, 음식 배달이 가능한 시간 K가 매개변수로 주어질 때, 음식 주문을 받을 수 있는 마을의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항
  • 마을의 개수 N은 1 이상 50 이하의 자연수입니다.
  • road의 길이(도로 정보의 개수)는 1 이상 2,000 이하입니다.
  • road의 각 원소는 마을을 연결하고 있는 각 도로의 정보를 나타냅니다.
  • road는 길이가 3인 배열이며, 순서대로 (a, b, c)를 나타냅니다.
    • a, b(1 ≤ a, b ≤ N, a != b)는 도로가 연결하는 두 마을의 번호이며, c(1 ≤ c ≤ 10,000, c는 자연수)는 도로를 지나는데 걸리는 시간입니다.
    • 두 마을 a, b를 연결하는 도로는 여러 개가 있을 수 있습니다.
    • 한 도로의 정보가 여러 번 중복해서 주어지지 않습니다.
  • K는 음식 배달이 가능한 시간을 나타내며, 1 이상 500,000 이하입니다.
  • 임의의 두 마을간에 항상 이동 가능한 경로가 존재합니다.
  • 1번 마을에 있는 음식점이 K 이하의 시간에 배달이 가능한 마을의 개수를 return 하면 됩니다.
입출력 예
N road K result
5 [[1,2,1],[2,3,3],[5,2,2],[1,4,2],[5,3,1],[5,4,2]] 3 4
6 [[1,2,1],[1,3,2],[2,3,2],[3,4,3],[3,5,2],[3,5,3],[5,6,1]] 4 4

[문제 풀이]

우선, 이 문제는 다익스트라 알고리즘을 적용하면 쉽게 풀 수 있는 문제다.

다익스트라 알고리즘에 대해 아직 잘 모른다면 아래 포스팅에서 확인하면 도움이 될 것 같다.

 

[Algorithm] - Dijkstra(다익스트라) 알고리즘

이론 Dijkstra(다익스트라) 알고리즘이란, 그래프의 한 정점에서 모든 정점까지의 최단 거리를 각각 구하는 알고리즘(최단경로 문제)이다. 처음 작성된 알고리즘은 시간복잡도 O(N^2)을 가지는데,

mocha-bro.tistory.com

위 포스팅을 읽었다는 전제하에 내가 문제를 푼 방식에 대해 얘기하려고 한다..

우선, 최단거리를 저장할 배열을 마을 최대 개수로 만들어주고, 초기값을 INT_MAX로 설정해준다.

=> vector<int> d(51,INT_MAX)

 

입력으로 들어오는 값은 마을 개수(N), 도로 정보(road), 배달 제한 시간(K)가 주어진다.

우리는 우선순위 큐를 이용해서 문제를 풀 것이기 때문에.. 입력으로 들어온 road를 조금 가공해서 사용할 것이다.

vector<pair<int,int>> a[N]라는 배열을 만들어서 각 노드에서 {연결된 다른 노드, 비용} 을 저장할 것이다.

이때 주의할 점은, 우리가 지금 풀고 있는 문제는 방향이 없는 그래프이기 때문에 서로의 노드에 연결된 노드의 인덱스를 저장해야 한다.

예를들어, a[1] = {2, 5} <=> a[2] = {1, 5} 와 같이 각각의 노드에 연결된 노드의 인덱스와 비용을 넣어주어야 한다.

priority_queue<pair<int,int>> pq를 만들어서 {0(비용),시작노드}을 넣어준다.

이후에는 다익스트라 포스팅에서 얘기했듯이 비용이 적은것을 먼저 탐색하기 위해 기준이되는 pair의 첫번째에 비용을 넣어주고, 동일한 과정을 반복하면 된다.

 

다익스트라 알고리즘 과정이 모두 끝났다면 배열 d에 모든 노드에 대해 최단시간이 저장되어 있다.

반복문을 통해 배열 d를 순회하여 배달 제한시간인 K보다 작거나 같은 마을의 개수를 세서 리턴하면 되겠다.

시작마을도 포함해야한다 !

파이팅 !

코드가 깨끗하고 명확하게 보일진 모르겠지만, 누군가에게 도움이 될 수도.. 있기에..

더보기
#include <iostream>
#include <vector>
#include <queue>
#include <limits.h>

using namespace std;
vector<int> d(51,INT_MAX);

int solution(int N, vector<vector<int> > road, int K) {
    int answer = 0;
    vector<pair<int,int>> a[51];
    d[1] = 0 ;
    priority_queue<pair<int,int>> pq; // (time, city)
    pq.push(make_pair(0,1));
    for(int i =0; i < road.size(); i++)
    {
        a[road[i][0]].push_back({road[i][1],road[i][2]});
        a[road[i][1]].push_back({road[i][0],road[i][2]});
    }
    
    while(pq.empty() == false)
    {
        int distance = -pq.top().first;
        int city = pq.top().second;
        pq.pop();
        if(d[city] < distance) continue;
        for(int i =0; i < a[city].size(); i++)
        {
            int nextCity = a[city][i].first;
            int nextDistance = distance + a[city][i].second;
     
            if(nextDistance < d[nextCity])
            {
                d[nextCity] = nextDistance;
                pq.push(make_pair(-nextDistance, nextCity));
            }
        }
    }
    
    
    for(int i =1; i <= N; i++)
    {
        if(d[i] <= K) answer++;
    }
    return answer;
}
복사했습니다!