C# 코딩테스트 강좌, 최단 경로 구하기

이 강좌에서는 C#을 사용하여 알고리즘 시험에서 흔히 출제되는 “최단 경로 구하기” 문제를 풀이해 보겠습니다. 이 주제는 그래프 이론의 기본 개념을 이해하고, 알고리즘 문제 해결 능력을 배양하는 데 매우 유용합니다. 특히, Dijkstra 알고리즘과 같은 인기 있는 알고리즘을 적용하여 이 문제를 어떻게 해결할 수 있는지 살펴보겠습니다.

문제 설명

다음은 “최단 경로 구하기” 문제의 예제입니다:

한 마을에는 N개의 집이 있고, 이 집들은 간선으로 연결되어 있습니다. 각 간선은 이동하는데 소요되는 시간을 나타냅니다. 이제 A 집에서 B 집까지 가는 가장 빠른 경로를 구하세요. 입력으로는 집의 수 N, 간선의 수 M, 각 간선의 정보(시작 집, 끝 집, 소요 시간)가 주어지고, 마지막으로 A 집과 B 집의 번호가 주어집니다.

입력 형식

  • 첫 번째 줄: 집의 수 N (1 ≤ N ≤ 1000)
  • 두 번째 줄: 간선의 수 M (1 ≤ M ≤ 10000)
  • 세 번째 줄부터 M + 2번째 줄까지: 간선 정보 (시작 집, 끝 집, 소요 시간)
  • 마지막 줄: A 집 번호와 B 집 번호

출력 형식

가장 빠른 경로의 소요 시간을 출력합니다. 만약 A 집에서 B 집으로 갈 수 없는 경우 -1을 출력합니다.

해결 방안

이 문제를 해결하기 위해 우리는 그래프 이론의 Dijkstra 알고리즘을 사용합니다. 이 알고리즘은 음의 가중치가 없는 그래프에서 최단 경로를 구하는 데 매우 효과적입니다.

Dijkstra 알고리즘

Dijkstra 알고리즘은 시작 노드에서 다른 모든 노드까지의 최단 경로를 구하는 그리디 알고리즘입니다. 이 알고리즘의 주요 아이디어는 다음과 같습니다:

  1. 출발 노드의 최단 거리를 0으로 초기화하고, 다른 모든 노드의 거리는 무한대로 초기화합니다.
  2. 우선순위 큐를 사용하여 현재 노드에서 가장 거리가 짧은 노드를 선택합니다.
  3. 선택된 노드를 기반으로 인접 노드의 거리 정보를 업데이트합니다.
  4. 모든 노드의 최단 거리를 계산할 때까지 이 과정을 반복합니다.

코드 구현

이제 Dijkstra 알고리즘을 C#으로 구현해보겠습니다. 아래는 알고리즘을 사용하여 최단 경로를 구하는 코드입니다:

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        int N = int.Parse(Console.ReadLine());
        int M = int.Parse(Console.ReadLine());

        // 그래프 초기화
        List>[] graph = new List>[N + 1];
        for (int i = 1; i <= N; i++)
        {
            graph[i] = new List>();
        }

        // 간선 입력 받기
        for (int i = 0; i < M; i++)
        {
            var line = Console.ReadLine().Split();
            int u = int.Parse(line[0]);
            int v = int.Parse(line[1]);
            int w = int.Parse(line[2]);
            graph[u].Add(new Tuple(v, w));
            graph[v].Add(new Tuple(u, w)); // 양방향 간선
        }

        var lastLine = Console.ReadLine().Split();
        int start = int.Parse(lastLine[0]);
        int end = int.Parse(lastLine[1]);

        // 최단 경로 구하기
        var result = Dijkstra(graph, N, start, end);
        Console.WriteLine(result);
    }

    static int Dijkstra(List>[] graph, int N, int start, int end)
    {
        int[] distances = new int[N + 1];
        bool[] visited = new bool[N + 1];
        int INF = int.MaxValue;

        // 거리를 INF로 초기화
        for (int i = 1; i <= N; i++)
        {
            distances[i] = INF;
        }
        distances[start] = 0;

        // 우선순위 큐
        SortedSet> pq = new SortedSet>();
        pq.Add(new Tuple(0, start));

        while (pq.Count > 0)
        {
            var current = pq.Min;
            pq.Remove(current);

            int currDist = current.Item1;
            int currNode = current.Item2;

            if (visited[currNode])
            {
                continue;
            }
            visited[currNode] = true;

            foreach (var neighbor in graph[currNode])
            {
                int nextNode = neighbor.Item1;
                int weight = neighbor.Item2;

                if (currDist + weight < distances[nextNode])
                {
                    distances[nextNode] = currDist + weight;
                    pq.Add(new Tuple(distances[nextNode], nextNode));
                }
            }
        }

        return distances[end] == INF ? -1 : distances[end];
    }
}

코드 설명

위의 코드는 최단 경로를 구하는 Dijkstra 알고리즘의 구현입니다:

  • 그래프 초기화: 집의 수 N과 간선의 수 M을 입력받고, 그래프를 리스트로 표현합니다.
  • 간선 입력: 각 간선 정보를 입력받아 그래프에 추가합니다. 이때, 양방향 간선으로 처리합니다.
  • Dijkstra 함수: 최단 경로를 구하는 로직을 포함합니다. 거리 배열과 방문 배열을 초기화하고, 우선순위 큐를 사용하여 가장 짧은 거리의 노드를 선택합니다.

결론

이번 강좌에서는 C#을 사용하여 최단 경로 문제를 풀어보았습니다. Dijkstra 알고리즘을 통해 그래프에서 최단 경로를 효과적으로 구할 수 있다는 것을 배웠습니다. 이러한 기법은 코딩 테스트 및 실제 개발에서도 매우 유용하게 사용될 수 있습니다. 다양한 문제를 풀어보며 이 알고리즘의 기초를 확실히 다져보시길 바랍니다.

이 글이 유익하시다면 댓글과 좋아요를 부탁드립니다. 다음에는 더 흥미로운 알고리즘 문제로 찾아뵙겠습니다!