POJ 3635 Full Tank 优先队列BFS

问题描述

有N个城市(编号0、1…N-1)和M条道路,构成一张无向图。

在每个城市里边都有一个加油站,不同的加油站的单位油价不一样。

现在你需要回答不超过100个问题,在每个问题中,请计算出一架油箱容量为C的车子,从起点城市S开到终点城市E至少要花多少油钱?

注意: 假定车子初始时油箱是空的。

输入格式
第一行包含两个整数N和M。

第二行包含N个整数,代表N个城市的单位油价,第i个数即为第i个城市的油价pi。

接下来M行,每行包括三个整数u,v,d,表示城市u与城市v之间存在道路,且车子从u到v需要消耗的油量为d。

接下来一行包含一个整数q,代表问题数量。

接下来q行,每行包含三个整数C、S、E,分别表示车子油箱容量、起点城市S、终点城市E。

输出格式
对于每个问题,输出一个整数,表示所需的最少油钱。

如果无法从起点城市开到终点城市,则输出”impossible”。

每个结果占一行。

数据范围
1 ≤ N ≤ 1000,
1 ≤ M ≤ 10000,
1 ≤ pi ≤ 100,
1 ≤ d ≤ 100,
1 ≤ C ≤ 100
样例

输入样例:
5 5
10 10 20 12 13
0 1 9
0 2 8
1 2 1
1 3 11
2 3 7
2
10 0 3
20 1 4
输出样例:
170
impossible

思路
        这道题就是一道堆优化的dijkstra问题, 我们使用二元组(city,fuel)来表示每个状态, 其中city为城市编号,fuel为油箱中剩余的汽油量,并使用记录数组dis[city][fuel] 存储最少花费
        对于每个问题,我们都单独进行-次优先队列 BFS.起始状态为(S,.0)。 每个状态(city,fuel)的分支有:
    1. 若fuel < C, 可以加1升油,扩展到新状态(city,fuel+1), 花费在城市city加1升油的钱。
    2. 对于每条从city 出发的边(city,next), 若边权大小w不超过fuel, 可以开车前往城市next, 扩展到新状态(next,fuel - w)。
    我们不断取出优先队列中“当前花费最少”的状态(堆顶)进行扩展,更新扩展到的新状态在记录数组d中存储的值,直到终点T的某个状态第一次被取出, 即可停止BFS,输出答案。

代码

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N = 1010, M = 20010, C = 110; //N为点 M为边 C为油
int n, m;
int head[N], e[M], w[M], ne[M], len;
int price[N];
int dis[N][C];
bool vis[N][C];
struct node{
	int d, u, c;
	bool operator <(const node &x) const{
		return d > x.d;
	}
};
void add(int v, int u, int ww){
	e[len] = u;
	w[len] = ww;
	ne[len] = head[v];
	head[v] = len++;
}
int dijkstra(int s, int end, int c){
	memset(dis, 0x3f, sizeof dis);
	memset(vis, false, sizeof vis);
	priority_queue<node> q;
	q.push({0, s, 0});
	dis[s][0] = 0;
	while(q.size()){
		node t = q.top();
		q.pop();
		if(t.u == end) return t.d;
		if(vis[t.u][t.c]) continue;
		vis[t.u][t.c] = true;
		if(t.c < c){
			if(dis[t.u][t.c + 1] > t.d + price[t.u]){
				dis[t.u][t.c + 1] = t.d + price[t.u];
				q.push({dis[t.u][t.c + 1], t.u, t.c + 1}); 
			}
		}
		for(int i = head[t.u]; ~i; i = ne[i]){
			int j = e[i];
			if(t.c >= w[i]){
				if(dis[j][t.c - w[i]] > t.d){
					dis[j][t.c - w[i]] = t.d;
					q.push({dis[j][t.c - w[i]], j, t.c - w[i]});
				}
			}
		}
	}
	return -1;
} 
int main(){
	scanf("%d%d", &n, &m);
	memset(head, -1, sizeof head);
	for(int i = 0; i < n; i++) scanf("%d", price + i);
	for(int i = 0; i < m; i++){
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c);
		add(b, a, c);
	}
	int t;
	scanf("%d", &t);
	while(t--){
		int a, b, c;
		scanf("%d%d%d", &c, &a, &b);
		int ans = dijkstra(a, b, c); 
		if(ans == -1) cout << "impossible" << endl;
		else cout << ans << endl;
	}
	return 0;
}
发布了54 篇原创文章 · 获赞 155 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_45432665/article/details/104124779