POJ 3635 Full Tank(最短路径变形 + 优先队列)
2013-04-02 12:31
399 查看
题意:
给 n 个城市 m 条路,每个城市有个加油站,但是收费单价不同,现给你几个查询并给定汽车的装油量, 问你从 S 城市到 T 城市的最小费用。
思路:
1. 如果是一条路径上面的加油站问题,比较容易解决,有动规方程:dp[i][j] 即到 i 站还剩下 j 升油的费用;
2. 现在涉及到图中的类似问题,并且数据规模还挺大的,直接针对每条边都进行一次转移,会 TLE,因为中间产生了很多无用的状态;
3. 因为要求最小费用,如果到达 T 时恰好油量为 0,则此时肯定是最优解的条件之一了。所以这个时候我们借鉴 dijstra 中最短路径的思路,
每次只加 1 升油,等价于把每个加油站又分解为 C + 1 个点,利用贪心的策略,每次寻找最小的费用即可.
给 n 个城市 m 条路,每个城市有个加油站,但是收费单价不同,现给你几个查询并给定汽车的装油量, 问你从 S 城市到 T 城市的最小费用。
思路:
1. 如果是一条路径上面的加油站问题,比较容易解决,有动规方程:dp[i][j] 即到 i 站还剩下 j 升油的费用;
2. 现在涉及到图中的类似问题,并且数据规模还挺大的,直接针对每条边都进行一次转移,会 TLE,因为中间产生了很多无用的状态;
3. 因为要求最小费用,如果到达 T 时恰好油量为 0,则此时肯定是最优解的条件之一了。所以这个时候我们借鉴 dijstra 中最短路径的思路,
每次只加 1 升油,等价于把每个加油站又分解为 C + 1 个点,利用贪心的策略,每次寻找最小的费用即可.
#include <iostream> #include <algorithm> #include <queue> using namespace std; const int MAXN = 1010; const int MAXM = 110; const int INFS = 0x3fffffff; struct ST { int u, fuel, cost; ST(int _u, int _fuel, int _cost) : u(_u), fuel(_fuel), cost(_cost) {} bool operator < (const ST& other) const { return cost > other.cost; } }; struct edge { int v, d; edge* next; } *V[MAXN], ES[MAXN*10*2]; int EC, price[MAXN], dp[MAXN][MAXM]; bool vis[MAXN][MAXM]; void addedge(int u, int v, int d) { ES[++EC].next = V[u]; V[u] = ES + EC; V[u]->v = v; V[u]->d = d; } int bfs(int s, int t, int vol) { priority_queue<ST> Q; Q.push(ST(s, 0, 0)); dp[s][0] = 0; while (!Q.empty()) { int u = Q.top().u; int fuel = Q.top().fuel; int cost = Q.top().cost; Q.pop(); vis[u][fuel] = true; if (u == t) return cost; if (fuel + 1 <= vol && !vis[u][fuel+1] && dp[u][fuel+1] > dp[u][fuel] + price[u]) { dp[u][fuel+1] = dp[u][fuel] + price[u]; Q.push(ST(u, fuel+1, dp[u][fuel+1])); } for (edge* e = V[u]; e; e = e->next) { int v = e->v; int f = fuel - e->d; if (f >= 0 && !vis[v][f] && dp[v][f] > cost) { dp[v][f] = cost; Q.push(ST(v, f, cost)); } } } return -1; } int main() { int n, m; while (~scanf("%d%d", &n, &m)) { for (int i = 0; i < n; i++) scanf("%d", &price[i]); EC = 0; memset(V, 0, sizeof(V)); for (int i = 0; i < m; i++) { int u, v, d; scanf("%d%d%d", &u, &v, &d); addedge(u, v, d); addedge(v, u, d); } int cases; scanf("%d", &cases); while (cases--) { int vol, s, t; scanf("%d%d%d", &vol, &s, &t); for (int i = 0; i <= n; i++) for (int j = 0; j <= vol; j++) dp[i][j] = INFS, vis[i][j] = false; int ans = bfs(s, t, vol); if (ans != -1) printf("%d\n", ans); else printf("impossible\n"); } } return 0; }
相关文章推荐
- POJ 3635 Full Tank? (最短路变形,BFS+优先队列)
- POJ-3635 Full Tank? 变形最短路
- POJ-3635-Full Tank?-spfa+ 优先队列
- POJ 3635 Full Tank? 最短路变形
- POJ 3635 Full Tank? (最短路变形,BFS+优先队列)
- poj 1258 Agri-Net dijkstra迪杰斯特拉算法,最短路径问题的变形,最小生成树
- poj 1860 最短路径变形
- [ACM] POJ 2253 Frogger (最短路径变形,每条通路中的最长边的最小值)
- POJ 3255 Roadblocks (Dijkstra求最短路径的变形)(Dijkstra求次短路径)
- POJ 3635 Full Tank?
- POJ 3635:Full Tank?
- POJ 3635 Full Tank?
- POJ 3635 Full Tank? (dp)
- poj 3635/hdu 1676 Full Tank? 车辆加油+最短路
- [ACM] POJ 2253 Frogger (最短路径变形,每条通路中的最长边的最小值)
- POJ 3635 Full Tank? 最短路DP
- poj 3635 Full Tank? ( bfs+dp思想 )
- POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
- poj 3635/hdu 1676 Full Tank? 车辆加油+最短路
- poj 3311 Hie with the Pie 旅行商问题变形 记录最短路径压缩状态