본문으로 바로가기

출처 : programmers.co.kr/learn/courses/30/lessons/12978

 

코딩테스트 연습 - 배달

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

programmers.co.kr

 

고려사항

  • 최단 경로 찾기 문제 중 플로이드-워셜 알고리즘을 사용했다.
  • 일반적으로 플로이드 워셜 알고리즘은 모든 노드에서 모든 노드로의 최단거리를 한 번에 구할 수 있지만,
    시간복잡도가 n^3 으로 매우 느려서 노드의 수가 작아야지만 사용 가능하다.
    이 문제는 N이 50이라 사용 가능하다.
  • INF 는 문제조건에 따라 다르지만 이 문제에서는 10억을 사용하면 충분하다.
    (35 라인의 fw[i][k] + fw[k][j] 에서 정수 범위를 벗어날 수 있으니 주의한다! )

  • 13 - 32 를 통해 인접 행렬을 초기화 해준다.
    여러 간선으로 연결되어 있다면 그 중 최소 값으로! 연결 안되어 있으면 INF으로!
  • 정말정말 간단한 3중 포문으로 모든 노드에서 모든 노드로 가는 최단 길이를 구해준다.
  • f[1][i] 를 검사하면서 K보다 작은 경로의 수를 세어준다.
  • 같은 문제를 다익스트라 알고리즘을 사용해서 풀어 작성한 글도 있다!

 

#include <iostream>
#include <vector>
#include <algorithm>
#define INF 1000000000
using namespace std;

int fw[51][51];

int solution(int N, vector<vector<int> > road, int K) {
    int answer = 0;
    int from, to, w;
    
    for(int i=1;i<=N;++i){
        for(int j=1;j<=N;++j){
            if(i == j){
                fw[i][j] = 0;
            }else{
                fw[i][j] = INF;
            }
        }
    }
    
    for(vector<int> v : road){
        from = v[0];
        to = v[1];
        w = v[2];
        
        fw[from][to] = min(fw[from][to], w);
        fw[to][from] = min(fw[to][from], w);
    }
    
    for(int k=1;k<=N;++k){
        for(int i=1;i<=N;++i){
            for(int j=1;j<=N;++j){
                fw[i][j] = min(fw[i][j], fw[i][k] + fw[k][j]);
            }
        }
    }
    
    for(int i=1;i<=N;++i){
        if(fw[1][i] <= K){
            ++answer;
        }
    }

    return answer;
}