poj 3635 Full Tank? (优先队列 + bfs)

http://poj.org/problem?id=3635

题意:有 n 个城市  ,每个 城市的 油价 不一样 ,已知 各 城市之间的距离 ,(假设 一  单位 距离 耗费一单位的 油量)一辆车 的  油箱 最多可以 装 c 升油,求从 s  到 e,的 最小 花费油量,如果不能到达 输出 impossible 。

题解:一开始 自己 写了 个,到达每一点后枚举 可以 增加的 油量 结果 tle (太多 无用的状态了)。。。。。。

 

dp[i][j]   表示 到达 城市  i  剩余油量 为 j  的 最小花费;

首先到达每个城市的后 要加的 油量 是 不确定 的 ,所以 我们要 将  每一个城市 拆成 c+ 1 个点,(不是直接的拆分),在 每一个 状态节点  我们有 两种选择 ,1  : 油量  加 1  (这个 就 相当于 拆分 成了  c+1 个节点);2:不加油 直接 走向  可 扩展的节点 。

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define eps  1e-12
 15  #define inf   0x7fffffff
 16 
 17  // freopen("data.txt","r",stdin);
 18  const  double pi  = acos(- 1.0);
 19 typedef   __int64  ll;
 20  const  int maxn =  1200 ;
 21  using  namespace std;
 22  struct node
 23 {
 24 
 25      int v;
 26      int len ;
 27      int next ;
 28 }p[maxn* 10* 2] ;
 29  struct qnode
 30 {
 31      int d;
 32      int  u ;
 33      int cost ;
 34     qnode( int x, int y, int z):u(x),d(y),cost(z){}
 35     friend  bool  operator < (qnode a,qnode b)
 36     {
 37          return  a.cost > b.cost ;
 38     }
 39 };
 40  int num,a[maxn],next[maxn],dp[maxn][ 102],n,m,vis[maxn][ 102];
 41  void add( int u , int  v, int len)
 42 {
 43     p[num].v = v;
 44     p[num].len = len ;
 45     p[num].next = next[u] ;
 46     next[u] = num++;
 47 }
 48 priority_queue<qnode>que;
 49  int bfs( int s, int e, int c)
 50 {
 51 
 52      int i , j ;
 53      while(!que.empty())que.pop();
 54 
 55      for(i =  0 ; i <= n;i++ )
 56     {
 57          for(j =  0; j<= c;j++)
 58            dp[i][j] = inf ;
 59     }
 60     
 61    CL(vis, 0);
 62    
 63    dp[s][ 0] =  0 ;
 64    
 65    que.push(qnode(s, 0, 0));
 66 
 67     while(!que.empty())
 68    {
 69        qnode  b = que.top();que.pop();
 70 
 71         int u = b.u;
 72         int cost = b.cost;
 73         int d = b.d ;
 74         vis[u][d] =  1; //  标记  已经找到了 的 最小的  ,下面就不用 再扩展的 此节点了
 75           if(u == e)  return  cost ; //  用的是 优先队列 所以 出来的定是 最小的 ;
 76 
 77         if(d+ 1 <= c &&!vis[u][d +  1] && dp[u][d+ 1]> dp[u][d] + a[u]) // 油量 加 1
 78         {
 79            dp[u][d +  1] = dp[u][d] + a[u] ;
 80            que.push(qnode(u,d+ 1,dp[u][d+ 1]));
 81 
 82        }
 83         for(i = next[u];i!= - 1;i = p[i].next) //  直接 走向 相邻 节点 ;
 84         {
 85             int v = p[i].v ;
 86             int len = p[i].len ;
 87 
 88             if(d >= len &&!vis[v][d - len] && dp[v][d - len] > cost)
 89            {
 90                dp[v][d - len] = cost ;
 91                que.push(qnode(v,d - len,cost));
 92            }
 93 
 94 
 95        }
 96 
 97 
 98    }
 99 
100 
101      return - 1 ;
102 }
103  int main()
104 {
105      // freopen("data.txt","r",stdin);
106        int s,e,c,i,x,y,d,q;
107       while(~scanf( " %d%d ",&n,&m))
108      {
109           for(i =  0;i < n;i++)  scanf( " %d ",&a[i]) ;
110 
111         CL(next,- 1) ;
112         num =  0 ;
113          for(i =  0 ;i< m;i++)
114        {
115          scanf( " %d%d%d ",&x,&y,&d);
116          add(x,y,d);
117          add(y,x,d);
118        }
119 
120        scanf( " %d ",&q);
121 
122          while(q--)
123         {
124            scanf( " %d%d%d ",&c,&s,&e);
125              int ans = bfs(s,e,c);
126              if(ans != - 1)printf( " %d\n ",ans);
127              else puts( " impossible ");
128         }
129      }
130 
131 }

 

 

 

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