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

【题意】 给你 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;
}
 
posted @ 2013-04-22 20:13  AbandonZHANG  阅读(136)  评论(0编辑  收藏  举报