POJ1724 价格合适的最短路(广搜BFS)

来源:互联网 发布:java instance单例 编辑:程序博客网 时间:2024/05/02 00:30

有编号为1-N的城市,这些城市之间存在一些单向路径,通过某条路径需要支付与路径长度一样的金币。BOB要从城市1到城市N,但他的金币数是有限的,现在要求找出从第1个城市到第N个城市的一条路径,既满足BOB支付得起路费,又满足总路径长度最小。

有点类似最短路,但因为有两个约束条件,所以说成广搜更加合适。维护一个优先队列,队列中存放的状态包括到达某个点剩下的金币和走过的路径长度,其中剩下的金币数必须为非负,队头元素是路径最小的。可以看出优先队列中存放的是合法的状态。但状态数目太多,无法全部考虑,因此需要加剪枝条件。可以为每个点存放两种状态,第一种是到达当前点走过的路径长度最小,另一种是到达当前点剩下的金币数最多。对于一个新状态,如果它可以更新以上两种状态之一或全部,则把该状态入队,否则不入队,因为比它更优的状态已经入过队了。最后的答案其实就是最后一个点的路径最短的状态。输出该最短的路径即可。

#include <iostream>#include <cstdio>#include <climits>#include <algorithm>#include <queue>using namespace std;const int N = 105;const int E = 10005;const int MAX = 0xfffffff;struct Edge {int pnt;int dis;int cost;int next;};Edge edge[E];int neigh[N];int cur;int n, m, e;int ans;int dis1[N], coin1[N];//距离最小的状态int dis2[N], coin2[N];//金币最多的状态struct Qnode{int pnt;int dis;int coin;Qnode(int _pnt, int _dis, int _coin): pnt(_pnt), dis(_dis), coin(_coin){}bool operator < (const Qnode& node) const{return dis > node.dis;}};void init(){cur = 0;for (int i = 0; i < n; ++i) neigh[i] = -1;}void bfs(){ans = MAX;for (int i = 0; i < n; ++i){dis1[i] = MAX;dis2[i] = MAX;coin1[i] = -1;coin2[i] = -1;}priority_queue<Qnode> pq;Qnode node(0, 0, m);int pnt, te, dis, coin;bool b1, b2;pq.push(node);while (!pq.empty()){node = pq.top();pq.pop();te = neigh[node.pnt];while (te != -1){pnt = edge[te].pnt;if (node.coin - edge[te].cost >= 0){if (pnt == n - 1 && node.dis + edge[te].dis < ans) ans = node.dis + edge[te].dis; else if (pnt < n - 1) {dis = node.dis + edge[te].dis;coin = node.coin - edge[te].cost;b1 = b2 = false;if (coin > coin2[pnt] || coin == coin2[pnt] && dis < dis2[pnt]){b1 = true;coin2[pnt] = coin;dis2[pnt] = dis;}if (dis < dis1[pnt] || dis == dis1[pnt] && coin > coin1[pnt]){b2 = true;coin1[pnt] = coin;dis1[pnt] = dis;}if (b1 || b2) pq.push(Qnode(pnt, dis, coin));}}te = edge[te].next;}}}int main(){int beg, end, dis, cost;scanf("%d%d%d", &m, &n, &e);init();for (int i = 0; i < e; ++i){scanf("%d%d%d%d", &beg, &end, &dis, &cost);--beg;--end;edge[cur].pnt = end;edge[cur].dis = dis;edge[cur].cost = cost;edge[cur].next = neigh[beg];neigh[beg] = cur;++cur;}bfs();if (ans == MAX) ans = -1; printf("%d\n", ans);return 0;}