题意:有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;
}