题意:n个城市,m条无向边,每个城市油价不一样。q次询问,给定起点s,终点e,求问最便宜路径。 油箱一开始设为0,假设每单位距离消耗1L汽油。
分析:dijkstra变形,设d[u][fuel] 表示到达城市u剩余油量为fuel的最小花费代价。这里很多状态是无用的,不需要全部求出来,每次加油一升一升的加。
代码如下:
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF = 1e9;
const int maxn = 1000+10;
int p[maxn];
int n,m,tot;
struct Edge{
int from,to,dist;
};
vector<Edge>edges;
vector<int>G[maxn];
int q,s,e,c;
inline void add_edge(int u, int v, int d){
edges.push_back((Edge){u,v,d});
tot = edges.size() - 1;
G[u].push_back(tot);
}
void Read(){
scanf("%d %d",&n,&m);
for (int i=0; i<n; i++) scanf("%d",&p[i]);
for (int i=0; i<=n; i++) G[i].clear();
edges.clear();
tot = 0;
int u,v,d;
for (int i=1; i<=m; i++) {
scanf("%d %d %d",&u,&v,&d);
add_edge(u,v,d);
add_edge(v,u,d);
}
}
int d[maxn][100+5];
struct HeapNode{
int cost,f,u;
bool operator <(const HeapNode &rhs) const {
return cost > rhs.cost;
}
};
priority_queue<HeapNode>que;
int dijkstra(int s,int t, int c){
memset(d,-1,sizeof(d));
while (!que.empty()) que.pop();
que.push((HeapNode){0,0,s});
HeapNode x,Q;
Edge e;
int u,v,tmp;
while (!que.empty()){
x = que.top(); que.pop(); u = x.u;
if (u == t) return x.cost;
for (int i=0; i<G[u].size(); i++) {
e = edges[G[u][i]];
if (e.dist > c) continue;
if (x.f >= e.dist) {
tmp = x.f - e.dist;
if (d[e.to][tmp] == -1 || d[e.to][tmp] > x.cost) {
d[e.to][tmp] = x.cost;
Q.u = e.to;
Q.cost = x.cost;
Q.f = tmp;
que.push(Q);
}
}
if (x.f < c) {
if (d[x.u][x.f+1] == -1 || d[x.u][x.f+1]>d[x.u][x.f]+p[u]){
d[x.u][x.f+1] = d[x.u][x.f] + p[u];
Q.f = x.f+1;
Q.u = x.u;
Q.cost = x.cost + p[u];
que.push(Q);
}
}
}
}
return -1;
}
int main(){
Read();
scanf("%d",&q);
while (q--){
scanf("%d %d %d",&c,&s,&e);
int ans = dijkstra(s,e,c);
if (ans == -1) printf("impossible\n"); else printf("%d\n",ans);
}
return 0;
}