Loading [MathJax]/jax/output/CommonHTML/jax.js
본문 바로가기

Problem Solving/Baekjoon Online Judge (Gold)

백준 30869 - 빨리 기다리기 (C++)

문제

  • 문제 링크
  •   
       BOJ 30869 - 빨리 기다리기 
      
  • 문제 요약
  • N개의 버스 정류장에 대해 M개의 버스 노선 정보가 주어진다.
    '빨리 기다리기'를 최대 K번까지 사용할 수 있을 때, 1번 정류장에서 N번 정류장까지 가는 데에 걸리는 최소 시간을 구해보자.
  • 제한
  • TL : 2 sec, ML : 1024 MB

  • 2N500
  • 0K500
  • 1M250,000
  • 1ti,gi10,000

알고리즘 분류

  • 그래프 이론 (graphs)
  • 다익스트라 (dijkstra)

풀이

그래프에서 두 정점쌍 간의 최단 거리는 기본적으로 다익스트라를 이용해 쉽게 구할 수 있다.
그런데 이번 문제에선, 고려해야 할 것들이 조금 있다.

  • 간선마다 배차 간격이 존재한다.
  • 최대 K번까지 '빨리 기다리기'를 사용해 배차 간격을 무시할 수 있다.


  • 정점 now까지 cost의 시간이 걸렸고 cnt번의 '빨리 기다리기'를 사용했다고 해보자. 동시에 정점 nxt를 향하는 가중치 weight, 배차 간격 g인 간선을 보고 있다고 해보자.

    문제 정의에 따라 이 순간 취할 수 있는 행동은 다음과 같을 것이다.

    • costg나누어 떨어질 때
      • 이 때는 배차 간격을 신경 쓸 필요 없이, 바로 출발할 수 있다. 소요 시간은 cost+weight.
    • costg나누어 떨어지지 않을 때
      • cnt<k 라면, '빨리 기다리기'를 사용해 nxt로 이동할 수 있다. 이 역시 소요 시간은 cost+weight.
      • 배차가 될 때까지 기다렸다가 nxt로 이동한다. cost+weight기다린 시간을 보정한 값이 소요 시간이다.



    이제 거리 테이블을 다음과 같이 정의하고, 위 내용대로 다익을 돌려주면 된다.

  • dist[x][y] : 1번 정점에서 '빨리 기다리기'를 y번 사용하여 x번 정점에 도착하는 데에 걸리는 최소 시간.



  • + 왜자꾸 틀리나 봤더니.. 간선을 양방향으로 추가해놓고 있었다.

    요새 죙일 학교 졸작 하느라 정신이 살짝 나간 건가?

    전체 코드


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include<bits/stdc++.h>
    using namespace std;
     
    int main()
    {
        ios_base::sync_with_stdio(0); cin.tie(0);
        int n, m, k; cin >> n >> m >> k;
     
        vector <tuple <intintint>> Gr[501];
        while (m--)
        {
            int s, e, t, g; cin >> s >> e >> t >> g;
            Gr[s].emplace_back(e, t, g);
        }
     
        priority_queue <tuple <intintint>> pq;
        vector <vector <int>> dist(501vector <int>(5012e9));
     
        for (pq.push({ dist[1][0= 010 }); pq.size();)
        {
            auto [cost, now, cnt](pq.top()); pq.pop();
            if (dist[now][cnt] < (cost *= -1))
                continue;
     
            for (auto& [nxt, weight, g] : Gr[now])
            {
                int cur(cost + weight);
                if (!(cost % g))
                {
                    if (dist[nxt][cnt] > cur)
                        pq.push({ -(dist[nxt][cnt] = cur), nxt, cnt });
                }
                else
                {
                    if (cnt < k && dist[nxt][cnt + 1> cur)
                        pq.push({ -(dist[nxt][cnt + 1= cur), nxt, cnt + 1 });
     
                    cur = cost / g * g + g + weight;
                    if (dist[nxt][cnt] > cur)
                        pq.push({ -(dist[nxt][cnt] = cur), nxt, cnt });
                }
            }
        }
     
        int ans(*min_element(dist[n].begin(), dist[n].end()));
        cout << (ans < 2e9 ? ans : -1);
    }
    cs


    comment