1 분 소요

합승택시요금 (프로그래머스 Level 3)

https://school.programmers.co.kr/learn/courses/30/lessons/72413

그래프 문제이며, 최단 경로와 관련된 문제이다
플로이드-워셜을 적용하여 풀 수 있겠다 싶었다
(총 자료의 개수가 약 200개 이하이므로, O(n^2)인 플로이드-워셜을 사용해도 될거라 판단하였다)

다만, 처음에는 s -> a -> b 와 s -> b -> a 중 작은 것을 고르면 된다고 생각하였으나
문제를 자세히 읽어보니 ‘s -> 공유 지점’, 이후
‘공유지점 -> a’, ‘공유지점 -> b’ 인 것을 확인할 수 있었다

플로이드-워셜로 만든 2차원 배열을 탐색하며,
각각의 ‘점’ 중 무엇을 공유 지점으로 삼았을 때
가장 적은 값이 나오는지 탐색하는 방식으로 풀 수 있었다

Code

#include <string>
#include <vector>
#include <unordered_map>
#include<limits.h>

using namespace std;

int solution(int n, int s, int a, int b, vector<vector<int>> fares) {

	// input 값 정리하기
	unordered_map<int, vector<pair<int, int>>> edges;
	for (const auto& fare : fares)
	{
		int begin = fare[0] - 1;
		int to = fare[1] - 1;
		int cost = fare[2];

		if (edges.find(begin) == edges.end())
		{
			edges[begin] = vector<pair<int, int>>();
		}

		edges[begin].push_back(make_pair(to, cost));

		if (edges.find(to) == edges.end())
		{
			edges[to] = vector<pair<int, int>>();
		}

		edges[to].push_back(make_pair(begin, cost));
	}

	// 약간의 매직 넘버 스럽지만
	// limit를 너무 크게 잡으면 overflow
	// 너무 낮게 잡으면 오답이 나온다 (limit보다 더 큰값이 생성)
	const int limit = INT_MAX / 10;
	vector<vector<int>> fw(n, vector<int>(n, limit));

	// 플로이드 - 워셜
	{
		for (int i = 0; i < n; i++)
		{
			fw[i][i] = 0;
		}

		for (const auto& edge : edges)
		{
			int s = edge.first;
			const auto& info = edge.second;
			for (const auto& i : info)
			{
				int t = i.first;
				int cost = i.second;
				fw[s][t] = cost;
			}
		}

		for (int k = 0; k < n; k++)
		{
			for (int i = 0; i < n; i++)
			{
				for (int j = 0; j < n; j++)
				{
					fw[i][j] = min(fw[i][j], fw[i][k] + fw[k][j]);
				}
			}
		}
	}

	// 특정한 최단 경로 문제
	int answer = limit;

	for (int i = 0; i < n; i++)
	{
		// 'i'가 A와 B가 나뉘는 '중간' 지점
		// 플로이드-워셜로 구한 i -> s , i -> a, i -> b의
		// 합이 가장 적은 것이 정답
		int totalCost = fw[s - 1][i] + fw[i][a - 1] + fw[i][b - 1];
		answer = min(answer, totalCost);
	}

	return answer;
}


댓글남기기