Uva 11367 Full Tank?(多状态最短路)

题意:有n个城市m条无向路连接,第i个城市的油价格为pi, 给出q个询问,每个询问包含起点s和终点t,还有油箱容量c,问从s到t最便宜的路径


思路:设d[i][j]:到达第i个城市还剩j升油时,所需要的最少花费,那么这里可以按花费直接用dijkstra,只是多加了一个状态而已


#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
const int INF = 1e9;
const int maxn = 1e3 + 10;
using namespace std;

struct P {
    int v, res, tal;
    P() {}
    P(int v, int r, int t) : v(v), res(r), tal(t) {}
    bool operator < (P p ) const { return tal > p.tal; }
};
int cost[maxn];
int d[maxn][110];
int dis[maxn][maxn];
int n, m, q, c, u, v;
vector<int> G[maxn];

int dijkstra(int s, int t) {
    for(int i = 0; i < n; i++) {
        for(int j = 0; j <= c; j++)
            d[i][j] = INF;
    }
    priority_queue<P> q;
    for(int i = 0; i <= c; i++) {
        d[s][i] = i * cost[s];
        q.push(P(s, i, d[s][i]));
    }
    while(!q.empty()) {
        P p = q.top(); q.pop();
        if(p.v == t) return p.tal;
        int vt = p.v, val = p.tal, re = p.res;
        if(d[vt][re] < val) continue;
        for(int i = re + 1; i <= c; i++) {
            int add = (i - re) * cost[vt];
            if(val + add >= d[vt][i]) continue;
            d[vt][i] = val + add;
            q.push(P(vt, i, d[vt][i]));
        }
        for(int i = 0; i < G[vt].size(); i++) {
            int v = G[vt][i];
            if(re < dis[vt][v]) continue;
            if(d[v][re - dis[vt][v]] <= val) continue;
            d[v][re - dis[vt][v]] = val;
            q.push(P(v, re - dis[vt][v], d[v][re - dis[vt][v]]));
        }
    }
    return -1;
}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        for(int i = 0; i < maxn; i++) {
            G[i].clear();
            for(int j = 0; j < maxn; j++)
                dis[i][j] = INF;
        }
        for(int i = 0; i < n; i++)
            scanf("%d", &cost[i]);
        while(m--) {
            int need;
            scanf("%d %d %d", &u, &v, &need);
            if(dis[u][v] == INF) {
                G[u].push_back(v);
                G[v].push_back(u);
            }
            need = min(need, dis[u][v]);
            dis[u][v] = dis[v][u] = need;
        }
        scanf("%d", &q);
        while(q--) {
            scanf("%d %d %d", &c, &u, &v);
            int ans = dijkstra(u, v);
            if(ans == -1) printf("impossible\n");
            if(ans != -1) printf("%d\n", ans);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值