题意:
有一个小偷,在n号点,他每天都会花费一定的钱,k天之后就会离开,你在1号点,存在m条边,每条边有一个花费,你每天只能走一条边,要求你在小偷离开之前抓到他,并且你自己行程所花的费用加上小偷的花费最少,求出满足上述题意的最少花费
做法:
分层图最短路,考虑将每一天的所有点看作一层图,所以对于你走一条边来说,实际上是从一层图走到了另一层图,并且在考虑花费的时候,需要考虑到当前是第几天,并把这一天的花费加在边权上面,最后找到在k天前到达n号点的最小花费即为答案,注意考虑不能到达的情况
代码:
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
const int MAXN = 1e4 + 5;
const ll mod = 20010905;
struct edge
{
int now;
ll w;
int nex;
}e[MAXN * 2];
int head[MAXN], tot;
ll dis[11][10005];
bool book[11][10005];
void init()
{
memset(head, -1, sizeof(head));
tot = 1;
}
void add(int a, int b, ll c)
{
e[tot] = edge{ b,c,head[a] };
head[a] = tot++;
}
ll cost[MAXN];
struct node
{
int now;
ll w;
int day;
};
auto cmp = [](node q, node w) {
return q.w > w.w;
};
void dij()
{
for (int i = 0; i < 11; i++)
for (int j = 2; j < 1005; j++)
dis[i][j] = 1e18;
priority_queue<node, vector<node>, decltype(cmp)>q(cmp);
q.push(node{ 1,0,0 });
while (!q.empty())
{
node u = q.top();
q.pop();
if (book[u.day][u.now])
continue;
book[u.day][u.now] = true;
for (int i = head[u.now]; i + 1; i = e[i].nex)
{
int v = e[i].now;
if (u.day + 1 > 10)
continue;
if (dis[u.day + 1][v] > dis[u.day][u.now] + cost[u.day + 1] + e[i].w)
{
dis[u.day + 1][v] = dis[u.day][u.now] + cost[u.day + 1] + e[i].w;
q.push(node{ v,dis[u.day + 1][v] ,u.day + 1 });
}
}
}
}
int main()
{
init();
int n, m, k;
sc("%d%d%d", &n, &m, &k);
for (int i = 0; i < m; i++)
{
int a, b; ll c;
sc("%d%d%lld", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
for (int i = 1; i <= k; i++)
{
sc("%lld", &cost[i]);
}
dij();
ll ans = 1e18;
for (int i = 0; i <= k; i++)
ans = min(ans, dis[i][n]);
if (ans == 1e18)
ans = -1;
pr("%lld\n", ans);
} 
京公网安备 11010502036488号