Print Friendly and PDF

기타/코딩테스트 공부

[필수 알고리즘] 폴로이드

나는야 개발자 2025. 5. 6. 14:24
반응형

개념

- 모든 노드에서 다른 모든 노드까지 가는 최소비용, O(V^3)

- 다익스트라는 한 노드 -> 모든 노드

 

작동원리

- 노드 j -> 노드 i 비용 배열 만들기, 초기값 : INF

- 간선의 값을 비용 배열에 반영

- 모든 노드에 대해 해당 노드 거쳐 비용이 작아질 경우 값 갱신

 

핵심코드

// 플로이드 워셜 알고리즘
for (int k = 1; k <= n; k++) // 거치는 값
{
    for (int j = 1; j <= n; j++) // 시작
    {
        for (int i = 1; i <= n; i++) // 도착
        {
            if (rs[j, k] != INF && rs[k, i] != INF && rs[j, i] > rs[j, k] + rs[k, i])
            {
                rs[j, i] = rs[j, k] + rs[k, i];
            }
        }
    }
}

- 3중 for문 이용

- rs[j, i] 현재 저장 된 값이 rs[j, k] + rs[k, i] 보다 크면 갱신

 

아이디어

- 거리 초기값을 무한대로 설정 후 자기 자신으로 가는 값은 0으로 설정

- 노드를 거쳐 가는 비용이 작아질 경우 값 갱신

 

시간복잡도

- V^3

 

변수

- 거리배열 : int[][]

 

Tip

- 그래프 거리 문제 나올때 사용

-> 한점에서 여러점 : 다익스트라

-> 여러점에서 여러점 : 플로이드

 

 

문제풀이

- 백준11404

 

1.

class num_11404
{
    static void Main(string[] args)
    {
        var sr = new StreamReader(Console.OpenStandardInput());
        var sw = new StreamWriter(Console.OpenStandardOutput());

        int n = Convert.ToInt32(sr.ReadLine());
        int m = Convert.ToInt32(sr.ReadLine());

        //플로이드는 모든 행의 크기가 동일하기 때문에 다차원 배열 사용 
        int[,] rs = new int[n + 1, n + 1];

        
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                //자신의 시작점은 0으로 초기화
                if (i == j)
                {
                    rs[i, j] = 0;
                }
                //아니면 전부 최대값 
                else
                {
                    rs[i, j] = int.MaxValue;
                }
            }
        }

        for (int i = 0; i < m; i++)
        {
            string[] input = sr.ReadLine().Split();
            int a = int.Parse(input[0]);
            int b = int.Parse(input[1]);
            int c = int.Parse(input[2]);

            //더 작은 것으로 삽입
            rs[a, b] = Math.Min(rs[a, b], c);
        }
    }
}

- int[,] rs = new int[n + 1, n + 1]; 행의 크기가 같기 때문에 다차원 배열로 선언 후 초기화

- rs[a, b] = Math.Min(rs[a, b], c);로 더 작은 값을 삽입

 

2. 

for (int i = 1; i <= n; i++)//거치는 값
{
    for (int j = 1; j <= n; j++)//시작
    {
        for (int k = 1; k <= n; k++)//도착
        {
            //최대값이 이면 넘기기
            if (rs[j, i] == int.MaxValue || rs[i, k] == int.MaxValue)
            {
                continue;
            }

            //시작 -> 도착 하는 값이 : 시작 -> 거치는 값 + 도착 -> 거치는 값 보다 작으면
            if (rs[j, k] > rs[j, i] + rs[i, k])
            {
                //값 갱신 
                rs[j, k] = rs[j, i] + rs[i, k];
            }
        }
    }
}


for (int i = 1; i <= n; i++)
{
    for (int j = 1; j <= n; j++)
    {
        //최대값이면 0으로 표기해돌라 했기 때문에 0으로 표기
        if (rs[i, j] == int.MaxValue)
        {
            sw.Write("0 ");
        }
        else
        {
            sw.Write($"{rs[i, j]} ");
        }
    }
    sw.WriteLine();
}

sw.Flush();
sw.Close();
sr.Close();

- 거치는 값, 시작, 도착을 이용해  시작 -> 도착 이 시작 -> 거치는 값 + 거치는 값 + 도착 보다 작으면 값 갱신

- 갱신 후 출력

 

최종코드

/*
1. 아이디어
- 모든 점 -> 모든 점 : 플로이드 사용
- 비용 배열 INF 초기화
- 간선 비용 대입
- 거쳐갈때 비용이 작을 경우, 갱신(for문 3번)

2. 시간복잡도
- 플로이드 : O(V^3)

3. 변수
- 비용 배열, int[][]
*/


class num_11404
{
    static void Main(string[] args)
    {
        var sr = new StreamReader(Console.OpenStandardInput());
        var sw = new StreamWriter(Console.OpenStandardOutput());

        int n = Convert.ToInt32(sr.ReadLine());
        int m = Convert.ToInt32(sr.ReadLine());

        //플로이드는 모든 행의 크기가 동일하기 때문에 다차원 배열 사용 
        int[,] rs = new int[n + 1, n + 1];

        
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                //자신의 시작점은 0으로 초기화
                if (i == j)
                {
                    rs[i, j] = 0;
                }
                //아니면 전부 최대값 
                else
                {
                    rs[i, j] = int.MaxValue;
                }
            }
        }

        for (int i = 0; i < m; i++)
        {
            string[] input = sr.ReadLine().Split();
            int a = int.Parse(input[0]);
            int b = int.Parse(input[1]);
            int c = int.Parse(input[2]);

            //더 작은 것으로 삽입
            rs[a, b] = Math.Min(rs[a, b], c);
        }

        for (int i = 1; i <= n; i++)//거치는 값
        {
            for (int j = 1; j <= n; j++)//시작
            {
                for (int k = 1; k <= n; k++)//도착
                {
                    //최대값이 이면 넘기기
                    if (rs[j, i] == int.MaxValue || rs[i, k] == int.MaxValue)
                    {
                        continue;
                    }

                    //시작 -> 도착 하는 값이 : 시작 -> 거치는 값 + 도착 -> 거치는 값 보다 작으면
                    if (rs[j, k] > rs[j, i] + rs[i, k])
                    {
                        //값 갱신 
                        rs[j, k] = rs[j, i] + rs[i, k];
                    }
                }
            }
        }


        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                //최대값이면 0으로 표기해돌라 했기 때문에 0으로 표기
                if (rs[i, j] == int.MaxValue)
                {
                    sw.Write("0 ");
                }
                else
                {
                    sw.Write($"{rs[i, j]} ");
                }
            }
            sw.WriteLine();
        }

        sw.Flush();
        sw.Close();
        sr.Close();
    }
}

 

참고영상

- 바로가기

 

 

반응형

'기타 > 코딩테스트 공부' 카테고리의 다른 글

[필수 알고리즘] 다익스트라  (0) 2025.05.06
[필수 알고리즘] MST  (0) 2025.05.05
[필수 알고리즘] DP  (0) 2025.05.05
[필수 알고리즘] 그리디  (0) 2025.05.05
[필수 알고리즘] 이진탐색  (0) 2025.05.03