1 분 소요

경로 찾기 (백준 Silver 1)

https://www.acmicpc.net/problem/11403

오랜만에 푸는 플로이드 - 워셜 알고리즘 문제이다
일반적인 길찾기 알고리즘은
출발 - 목적지 가 명확하게 정해져 있지만
‘모든 쌍’에 대한 각각의 최단 거리가 필요할 때는
다소 무거운 O(n^3)이더라도
플로이드 - 워셜을 적용하여 푸는것이 정답이다

다만 정점의 거리 사이에 음수 사이클이 없어야 하며
O(n^3)의 시간 복잡도를 가지기에
n의 개수가 지나치게 올라가는 경우엔 권장하지 않음
(그렇기에 n이 1천개가 넘어간다면
플로이드-워셜이 맞을까하는 의심을 가져보자)

플로이드 - 워셜

모든 정점의 쌍(i,j)에 대하여
중간의 경유 정점 ‘k’를 거쳐갔을 때
최단 거리가 갱신되는가
를 판단하는 알고리즘

따라서 기본적으로 갈 수 없는 거리의 길이를
‘무한대’ 등으로 잡아두고

i -> k -> j 의 거리가
i -> j 보다 짧은가 를 계산한 후
갱신하는 방식이다

출 -> 경 -> 목 으로 기억해보자

의사코드로 보자면

dist[i][j] = INF;

for(k)
 for(i)
  for(j)
   if(dist[i][k] + dist[k][j] < dist[i][j])
    dist[i][j] = dist[i][k] + dist[k][j]; // 갱신

적용하는 경우와
‘출발->경유->목적’ 인 순서만 기억한다면
어렵지 않다

풀이 결과

원래는 dfs나 bfs를 적용하여 풀려 하였으나
결국 ‘모든 쌍’에 적용해야 하며
여태까지의 ‘경로’를 저장하며 진행하는 방식으로
구현하는 것보다 플로이드 - 워셜로 거리를 구하고
그 거리가 초기값이 아니라면,
그냥 1을 출력하는 편이 더 간단하다고 판단하였다

Image

제출 코드

#include<iostream>
#include<vector>
#include<limits.h>

using namespace std;

int main()
{
	int n;
	cin >> n;

	const int semiV = INT_MAX / 2;

	vector<vector<int>> results(n, vector<int>(n, semiV));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			int t;
			cin >> t;
			if(t == 1)
				results[i][j] = t;
		}
	}

	for (int k = 0; k < n; k++)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (results[i][k] + results[k][j] < results[i][j])
				{
					results[i][j] = results[i][k] + results[k][j];
				}

			}
		}
	}
	
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (results[i][j] == semiV)
				cout << 0 << ' ';
			else
				cout << 1 << ' ';
		}
		cout << '\n';
	}

}

댓글남기기