题意:给定一张
n
个点
思路:最短路上的dp,如果求出所有的路径,那么我们需要做一次dp或者贪心来得到最小值,但实际上我们可以使用用heap优化的dij算法,以最小花费为权重,每次加一升油,来判断当前这个状态最远能走到那里。使用
dp[Vv][j−D(u,v)]=min(dp[Vv][j−D(u,v)],dp[Vu][j])
同时,在更新完成之后,尝试在当前点加油,状态转移方程为
dp[Vu][j+1]=min(dp[Vu][j+1],dp[Vu][j]+Pu)
总的时间复杂度为
O(T)=O(q∗c∗n∗logm)
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <string.h>
#include <cstring>
#include <cstdlib>
#include <set>
#include <algorithm>
#include <cctype>
#include<cmath>
#include <sstream>
using namespace std;
#define sp system("pause");
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 1050;
const double PI = acos(-1.0);
vector<pii>e[MAXN];
int pri[MAXN];
int dp[MAXN][120];
struct node
{
int p, c, w;
node(){}
node(int a, int b, int c) :p(a), c(b), w(c){}
friend bool operator<(const node &x, const node &y)
{
return x.w > y.w;
}
};
int dij(int st, int en, int cap)
{
for (int i = 0; i < MAXN; i++)for (int j = 0; j < 120; j++)dp[i][j] = 100000000;
priority_queue<node>pq;
dp[st][0] = 0;
pq.push(node(st, 0, 0));
while (!pq.empty())
{
node tmp = pq.top();
pq.pop();
if (tmp.p == en)return tmp.w;
int u = tmp.p;
for (int i = 0; i < e[tmp.p].size(); i++)
{
int v = e[u][i].first;
int d = e[u][i].second;
if (tmp.c-d>=0&&dp[v][tmp.c - d]>tmp.w)
{
dp[v][tmp.c - d] = tmp.w;
pq.push(node(v, tmp.c - d, tmp.w));
}
}
if (tmp.c < cap&&dp[u][tmp.c+1]>tmp.w+pri[u])
{
dp[u][tmp.c + 1] = tmp.w + pri[u];
pq.push(node(u, tmp.c + 1, dp[u][tmp.c + 1]));
}
}
return -1;
}
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = 0; i < MAXN; i++)e[i].clear();
for (int i = 0; i < n; i++)scanf("%d", pri + i);
for (int i = 0; i < m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
e[x].push_back(pii(y, z));
e[y].push_back(pii(x, z));
}
int q;
scanf("%d", &q);
while (q--)
{
int c, st, en;
scanf("%d%d%d", &c, &st, &en);
int ans = dij(st, en, c);
if (ans == -1)puts("impossible");
else printf("%d\n", ans);
}
}
}