ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다익스트라(dijkstra) 최단 경로
    알고리즘/백준 2021. 8. 30. 17:55

    풀이

    다익스트라 알고리즘은 탐욕법과 동적 계획법을 같이 사용합니다. i 노드까지 최단 경로를 구하는 점화식 dist[i]가 등장하며 이를 구하기 위해 매번 최선의 선택(최소 가중치)을 수행합니다. 기본적인 흐름은 다음과 같습니다. 시작 노드를 방문하면서 시작합니다.

     

    1. 방문한 노드에서 방문할 수 있는 다른 노드까지의 거리를 구합니다. 그 거리가 기존 값보다 짧으면 새로 갱신합니다.

     

    2. 거리가 새로 갱신된 노드만 우선순위 큐에 넣습니다. 중복 방문을 없애기 위해서입니다. 이 외에도 중복 방문을 막기 위한 코드가 한 줄 더 있습니다.

     

    3. 이 중에서 간선의 가중치가 최소인 노드를 방문합니다(우선순위 큐를 이용하면 최소 가중치를 쉽게 구할 수 있음).

     

    4. 1번으로 갑니다.

     

    코드

    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
    
    int N = 10, E = 19;
    const int INF = 100000000;
    
    vector<vector<int>> nodes(N, vector<int>(N));
    vector<int> dist(N, INF);
    using PairInt = pair<int, int>;
    
    void dijkstra(int start)
    {
    	// 방문할 노드를 담아두는 곳(최소 가중치인 곳)
    	// first는 방문한 노드까지의 최소 가중치, second는 방문한 노드
    	priority_queue<PairInt, vector<PairInt>, greater<PairInt>> pq; 
    	// 시작 노드의 가중치는 0
    	pq.push({ 0, start });
    	dist[start] = 0;
    	while (!pq.empty())
    	{
    		auto [length, current] = pq.top(); pq.pop();
    		if (dist[current] < length) continue;
    
    		for (int i = 0; i < nodes[current].size(); ++i)
    		{
    			if (0 == nodes[current][i]) continue;
    
    			auto sum = dist[current] + nodes[current][i];
    			if (sum < dist[i])
    			{
    				dist[i] = sum;
    				pq.push({ dist[i], i });
    			}
    		}
    	}
    }
    
    int main()
    {
    	nodes[0][1] = 10;
    	nodes[0][2] = 17;
    	nodes[0][3] = 30;
    	nodes[0][4] = 25;
    	nodes[0][5] = 23;
    	nodes[1][2] = 20;
    	nodes[2][4] = 17;
    	nodes[3][1] = 19;
    	nodes[3][6] = 24;
    	nodes[4][7] = 25;
    	nodes[4][8] = 39;
    	nodes[5][3] = 16;
    	nodes[5][4] = 28;
    	nodes[5][6] = 18;
    	nodes[6][9] = 20;
    	nodes[7][8] = 29;
    	nodes[8][5] = 20;
    	nodes[8][9] = 28;
    	nodes[9][7] = 40;	
    
    	dijkstra(0);
    
    	cout << dist[9] << endl;
    }

    방문을 하려고 우선 순위 큐에 삽입을 했는데 dist[i]를 갱신하는 과정에서 큐에 삽입한 값보다 dist[i]가 작아졌을 경우에는 방문하지 않습니다. 왜냐하면 dist[i]를 계산하면서 차후에 방문하기 위해 동일 {가중치, 노드}가 큐에 들어갔기 때문입니다. 그리고 이 코드는 배열의 개수를 고정해버렸기 때문에 문제에 그대로 적용하면 메모리 초과 오류가 날 수 있습니다. 그 경우 벡터를 이용해서 간선이 부여되는 만큼만 노드를 추가하면 됩니다.

    '알고리즘 > 백준' 카테고리의 다른 글

    [백준] 유기농 배추(1012번)  (0) 2021.09.17
    [백준] N-Queen 9663번  (0) 2021.09.07
    [백준] 2805번 나무 자르기  (0) 2021.08.29
    [백준] 3079번 입국 심사  (0) 2021.08.27
    [백준] 1920번 수 찾기  (0) 2021.08.27

    댓글

Designed by Tistory.