您的位置:首页 > 其它

POJ 3635 Full Tank? (最短路变形,BFS+优先队列)

2013-04-22 20:13 323 查看
【题意】
给你 n 个点,m 条边,每走 1 单位的路径都会花费 1 单位的 fuel ,并且不同的点灌油的油的价格是不同的,现在给你一些询问,每一个询问给你起点、终点以及油箱的容量,问你所需要的最少的花费可以从起点到达终点。

涉及两个维的图最短路,一个是费用,一个是地点。(比如在位置0有1升油是一个点,在位置0有2升油又是另外一个点)

如果把这个点抽象出来,把费用看过边,那么最少费用就可以类似dijsktra算法那样不断的加入点。

于是得到一个扩展结点的策略:

1.每一次加一升油(因为题目的条件这些都是整数,所以可以类似离散化处理,一点一点加入油)

2.如果加的油足够走到下一个结点,那就走到下一个结点吧(记得减去路上消耗的油,还有花费不变...)

(至于在第二次扩展时要不要加油,这个就不需要了.因为在第一种情况扩展结点的时候加油了...)

这里的BFS是把所有可扩展的节点都加入优先队列中,而Dijkstra是每次松弛了的点才加入,中间少了很多状态。但是思想都是一样的。不知道这题能不能像Dij那样做。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

struct node{
int u, v, w;
int next;
}edge[20003];
struct Status{
int u, fuel, cost;
friend bool operator < (const Status n1, const Status n2){
return n2.cost < n1.cost;
}
};
int head[1003], cnt;
int n, m;
int price[1003];
void init(){
mem(head, -1);
cnt = 0;
}
void add(int u, int v, int w){
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt ++;
return ;
}
priority_queue  > PQ;
bool vis[1003][103];
void push_PQ(int u, int f, int c){
Status tmp;
tmp.u = u;
tmp.fuel = f;
tmp.cost = c;
PQ.push(tmp);
}
int BFS(int c, int s, int e){
mem(vis, 0);
while(!PQ.empty()){
PQ.pop();
}
push_PQ(s, 0, 0);
while(!PQ.empty()){
Status tmp = PQ.top();
PQ.pop();
int u = tmp.u, fuel = tmp.fuel, cost = tmp.cost;
vis[u][fuel] = 1;
if (u == e){
return cost;
}
// we choose to add a unit fuel;
if (fuel < c && !vis[u][fuel+1]){
push_PQ(u, fuel+1, cost+price[u]);
}
// we choose to go to the next node;
for (int i = head[u]; i != -1; i = edge[i].next){
if (fuel >= edge[i].w && !vis[edge[i].v][fuel-edge[i].w]){
push_PQ(edge[i].v, fuel-edge[i].w, cost);
}
}
}
return -1;
}
int main(){
init();
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i ++){
scanf("%d", &price[i]);
}
for (int i = 0; i < m; i ++){
int tmpu, tmpv, tmpw;
scanf("%d %d %d", &tmpu, &tmpv, &tmpw);
add(tmpu, tmpv, tmpw);
add(tmpv, tmpu, tmpw);
}
int q, c, s, e;;
scanf("%d", &q);
while(q --){
scanf("%d %d %d", &c, &s, &e);
int ans = BFS(c, s, e);
if (ans == -1){
puts("impossible");
}
else{
printf("%d\n", ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: