题目描述:
给你一个图,每条边有长度l和花费c两个信息。
求从1~n的一条路,在总花费不超过k的情况下最短路是多少。
解题报告:
A*,用dij算法。
原点入优先队。
while(堆不空)
取出堆顶(按路径长度排序,长度相同按花费排序,都是取最小的)
如果堆顶是第n号节点,直接返回长度答案。
否则,遍历堆顶的每条边。
对于每条边,求出堆顶节点到边尾节点的花费和长度。
如果花费在限制以内,就入队。
堆空了,还没找到答案,返回-1,不成功。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define size 120
struct edge{int from, to, v1, v2, next;} e[20000];
struct node
{
int id, v1,
v2;
friend bool
operator < (const node a, const node b)
{
if (a.v1 == b.v1) return a.v2 > b.v2;
return a.v1 > b.v1;
}
};
int v[size], d[size], cnt, k, n, r;
void insert(int from, int to, int v1, int v2)
{
e[cnt].from
= from, e[cnt].to = to, e[cnt].v1 = v1, e[cnt].v2 = v2;
e[cnt].next
= v[from]; v[from] = cnt++;
}
int dij()
{
memset(d,
-1, sizeof(d));
priority_queue<node> que;
node ne =
{1, 0, 0};
que.push(ne);
while(!que.empty())
{
ne = que.top(); que.pop();
d[ne.id] = ne.v1;
if (ne.id == n) return d[n];
int id = v[ne.id];
while(id != -1)
{
node tmp = {e[id].to, ne.v1 + e[id].v1, ne.v2 + e[id].v2};
if (tmp.v2 <= k) que.push(tmp);
id = e[id].next;
}
}
return
-1;
}
int main()
{
scanf("%d%d%d", &k, &n,
&r);
memset(v,
-1, sizeof(v)); cnt = 0;
for(int i =
0; i < r; i++)
{
int a, b ,c, d;
scanf("%d%d%d%d", &a, &b,
&c, &d);
insert(a, b, c, d);
}
printf("%d\n", dij());
return
0;
}
加载中,请稍候......