본문으로 바로가기

출처 : 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;
}