abc325E 火车+班车的最短路

题面:有n座城市,从城市i到城市j可以坐班车,需要A*D[i][j]时间,也可以坐火车,需要B*D[i][j]+C时间。可以从班车换到火车,但反过来不行。换乘时间不计,求从城市1到城市n的最短时间。
范围:n<1000; A,B,C<1E6; D[i]][j]<1E6并且D[i][i]=0。

思路:先预处理出任意两城市之间的耗时,包括班车D[i][j]和火车d[i][j],然后边跑dijkstra边dp,即班车后续可以是班车或火车,而火车后续只能是火车。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)

const int N = 1005;
const int inf = 1E18;
int n, A, B, C, D[N][N], d[N][N], ans[N][2];
void dijkstra(int s) {
    rep(i,1,n) ans[i][0] = ans[i][1] = inf;
    priority_queue<tuple<int,int,int>> q;
    q.push({0,s,0});
    q.push({0,s,1});
    while (!q.empty()) {
        auto [c,x,f] = q.top(); q.pop();
        if (ans[x][0] == inf && f == 0) {
            ans[x][0] = -c;
            rep(i,1,n) {
                if (ans[i][0]==inf) {
                    q.push({c-D[x][i],i,0});
                }
                if (ans[i][1]==inf) {
                    q.push({c-d[x][i],i,1});
                }
            }    
        }
        if (ans[x][1] == inf) {
            ans[x][1] = -c;
            rep(i,1,n) {
                if (ans[i][1]==inf) {
                    q.push({c-d[x][i],i,1});
                }
            }
        }
    }
}
void solve() {
    cin >> n >> A >> B >> C;
    rep(i,1,n) rep(j,1,n) {
        cin >> D[i][j];
        if (i != j) {
            d[i][j] = D[i][j] * B + C;
            D[i][j] = D[i][j] * A;
        }
    }
    dijkstra(1);
    cout << min(ans[n][0],ans[n][1]) << "\n";
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2024-03-09 09:29  chenfy27  阅读(3)  评论(0编辑  收藏  举报