zoukankan      html  css  js  c++  java
  • 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;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    JAVA实验3 类与对象
    多种排序功能的实现
    (数据结构)HashTable的实现
    对string型变量的频率统计(文章单词检索)
    对int型变量的频率统计
    二叉搜索树中序迭代器的实现
    二叉搜索树的实现
    Prim最小生成树
    Kruscal最小生成树
    算法分析实践大作业
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114021.html
Copyright © 2011-2022 走看看