您的位置:首页 > 其它

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 个点,利用贪心的策略,每次寻找最小的费用即可.

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: