POJ3635 Full Tank?

Full Tank?

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7543   Accepted: 2444

Description

After going through the receipts from your car trip through Europe this summer, you realised that the gas prices varied between the cities you visited. Maybe you could have saved some money if you were a bit more clever about where you filled your fuel?

To help other tourists (and save money yourself next time), you want to write a program for finding the cheapest way to travel between cities, filling your tank on the way. We assume that all cars use one unit of fuel per unit of distance, and start with an empty gas tank.

Input

The first line of input gives 1 ≤ n ≤ 1000 and 0 ≤ m ≤ 10000, the number of cities and roads. Then follows a line with n integers 1 ≤ pi ≤ 100, where pi is the fuel price in the ith city. Then follow m lines with three integers 0 ≤ u, v < n and 1 ≤ d ≤ 100, telling that there is a road between u and v with length d. Then comes a line with the number 1 ≤ q ≤ 100, giving the number of queries, and q lines with three integers 1 ≤ c ≤ 100, s and e, where c is the fuel capacity of the vehicle, s is the starting city, and e is the goal.

Output

For each query, output the price of the cheapest trip from s to e using a car with the given capacity, or "impossible" if there is no way of getting from s to e with the given car.

Sample Input

5 5
10 10 20 12 13
0 1 9
0 2 8
1 2 1
1 3 11
2 3 7
2
10 0 3
20 1 4

Sample Output

170
impossible

Source

Nordic 2007

【题解】

设b[i][j]表示在第i个城市,剩余汽油j的答案

每次选答案最小的去拓展,拓展方案无非两种:买1个汽油或者走向下一个城市

注意如果新的方案答案比已有答案小,就不再加入优先队列了

其实出队的节点b[i][j],一定是最优的

很(一点也不)显然,没有更小的值去更新b[i][j]了,只能用b[i][j]去更新别人

很想dijkstra

复杂度O(n*clogn*c)

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <algorithm>
  6 #include <queue>
  7
  8 inline void read(int &x)
  9 {
 10     x = 0;char ch = getchar(), c = ch;
 11     while(ch < ‘0‘ || ch > ‘9‘)c = ch, ch = getchar();
 12     while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘, ch = getchar();
 13     if(c == ‘-‘)x = -x;
 14 }
 15
 16 const int MAXN = 2000 + 10;
 17 const int MAXM = 20000 + 10;
 18 const int MAXC = 200 + 10;
 19
 20 struct Edge
 21 {
 22     int u,v,w,next;
 23     Edge(int _u, int _v, int _w, int _next){u = _u;v = _v; w = _w; next = _next;}
 24     Edge(){}
 25 }edge[MAXM << 2];
 26 int head[MAXN], cnt;
 27
 28 inline void insert(int a, int b, int c)
 29 {
 30     edge[++cnt] = Edge(a,b,c,head[a]);
 31     head[a] = cnt;
 32 }
 33
 34 int n,m,value[MAXN],qq,b[MAXN][MAXC],s,e,c;
 35
 36 struct Node
 37 {
 38     int now, v, ans;
 39     Node(){}
 40     Node(int _now, int _v, int _ans){now = _now;v = _v; ans = _ans;}
 41 };
 42
 43 struct cmp
 44 {
 45     bool operator()(Node a, Node b)
 46     {
 47         return a.ans > b.ans;
 48     }
 49 };
 50
 51 std::priority_queue<Node, std::vector<Node>, cmp> q;
 52
 53 void bfs(int s, int e)
 54 {
 55     memset(b, 0x3f, sizeof(b));
 56     while(q.size())q.pop();
 57     q.push(Node(s, 0, 0));
 58     b[0][0] = 1;
 59     if(s == e)
 60     {
 61         printf("0\n");
 62         return;
 63     }
 64     register Node tmp;
 65     while(q.size())
 66     {
 67         tmp = q.top();q.pop();
 68         if(tmp.v + 1 <= c && b[tmp.now][tmp.v + 1] > tmp.ans + value[tmp.now])q.push(Node(tmp.now, tmp.v + 1, tmp.ans + value[tmp.now])), b[tmp.now][tmp.v + 1] = tmp.ans + value[tmp.now];
 69         for(register int pos = head[tmp.now];pos;pos = edge[pos].next)
 70         {
 71             if(tmp.v < edge[pos].w || b[edge[pos].v][tmp.v - edge[pos].w] <= tmp.ans)continue;
 72             if(edge[pos].v == e)
 73             {
 74                 printf("%d\n", tmp.ans);
 75                 return;
 76             }
 77             q.push(Node(edge[pos].v, tmp.v - edge[pos].w, tmp.ans));
 78             b[edge[pos].v][tmp.v - edge[pos].w] =  tmp.ans;
 79         }
 80     }
 81     printf("impossible\n");
 82 }
 83
 84 int main()
 85 {
 86     read(n);read(m);
 87     register int tmp1, tmp2, tmp3;
 88     for(register int i = 1;i <= n;++ i)read(value[i]);
 89     for(register int i = 1;i <= m;++ i)
 90     {
 91         read(tmp1), read(tmp2), read(tmp3);
 92         insert(tmp1 + 1, tmp2 + 1, tmp3);
 93         insert(tmp2 + 1, tmp1 + 1, tmp3);
 94     }
 95     read(qq);
 96     for(;qq;-- qq)
 97     {
 98         read(c);read(s);read(e);
 99         ++ s;++ e;
100         bfs(s, e);
101     }
102     return 0;
103 } 

POJ3635

时间: 2024-10-04 13:34:31

POJ3635 Full Tank?的相关文章

POJ3635 Full Tank?(DP+Dijkstra)

题目大概说,一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用,问从起点驾驶到终点的最少花费是多少? 这题自然想到图上DP,通过最短路来转移方程: dp[u][c]表示当前在u点油箱还有c单位油时的最少花费 不过,我T得好惨,因为在转移时我通过枚举在各个结点加多少油转移,这样对于每个状态都for一遍枚举,整个时间复杂度还得乘上转移的代价,即油箱最大容量... 事实上,状态dp[u][c]只需要向两个方向转移: 向dp[u]

poj练习题的方法

poj1010--邮票问题 DFSpoj1011--Sticks dfs + 剪枝poj1020--拼蛋糕poj1054--The Troublesome Frogpoj1062--昂贵的聘礼poj1077--Eightpoj1084--Square Destroyerpoj1085--Triangle War(博弈,極大極小搜索+alpha_beta剪枝)poj1088--滑雪poj1129--Channel Allocation 着色问题 dfspoj1154--letters (dfs)p

POJ 搜索题集

poj1010--邮票问题 DFS poj1011--Sticks dfs + 剪枝 poj1020--拼蛋糕 poj1054--The Troublesome Frog poj1062--昂贵的聘礼 poj1077--Eight poj1084--Square Destroyer poj1085--Triangle War(博弈,極大極小搜索+alpha_beta剪枝) poj1088--滑雪 poj1129--Channel Allocation 着色问题 dfs poj1154--lett

10.27--11.3 一周刷题记录

exgcd 贝祖定理推广 贝祖定理可以推广到n个,n>=2 ax+by+cz+...=k if(k%gcd(a,b,c,...)==0) 该式子有整数解 else 没有整数解 Forsaken喜欢数论 因为空间限制,直接省略掉sum数组 记得sum 开long long! int n; const int N=3e7+10; int v[N],p[N],tot_p; long long sum; inline void shai(){ rep(i,2,n){ if(v[i]==0){ v[i]=

UVA 11367 - Full Tank?(最短路+DP)

UVA 11367 - Full Tank? 题目链接 题意:给定一个无向图,每个点有一个加油站,有一个油价,现在一辆车,每次询问要从起点s走到t,邮箱容量为c,问最小代价 思路:dijkstra算法,d数组多一个状态,表示当前油量即可 不过这题如果每次都把所有状态转移完,挺费时间的,卡着时间过的 后面改成每次1升1升加油去转移状态,效率会比较快,因为有很多无用状态可以省去 代码: #include <cstdio> #include <cstring> #include <

poj3635Full Tank?[分层图最短路]

Full Tank? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7248   Accepted: 2338 Description After going through the receipts from your car trip through Europe this summer, you realised that the gas prices varied between the cities you v

hdu 4445 Crazy Tank(枚举)

http://acm.hdu.edu.cn/showproblem.php?pid=4445 要求发射的炮弹在都不落在friendly tank区域的条件下落在enemy tank区域的最多数目. 直接暴力枚举角度.. #include <stdio.h> #include <iostream> #include <map> #include <set> #include <bitset> #include <list> #inclu

HDOJ 4445 Crazy Tank

枚举角度 Crazy Tank Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4305    Accepted Submission(s): 833 Problem Description Crazy Tank was a famous game about ten years ago. Every child liked it. T

poj 3635 Full Tank? ( 图上dp )

题意: 已知每个点的加油站的油价单价(即点权),每条路的长度(边权). 有q个询问,每个询问包括起点s.终点e和油箱容量. 问从起点走到终点的最小花费.如果不可达输出impossible,否则输出最小的旅途费用. 算法: 其实要分析状态= =感觉就像是dp. 最直接的想法是  每到一个点都加上要走到下一个点所需要的油量.但是走的路不同,到底怎么处理加多少的问题呢? 因此想到分解状态,即拆点.每到一个点都+1单位的油量,然后把这个状态加入队列.另外如果现在油箱内的油足够达到下一点, 则更新状态,把