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; } 
                
               
              
             
           
          
         
        
       
      
    
 
   
 

你可能感兴趣的:(优先队列)