题意:平面上,要从起点到终点,中间有n个站台,站台之间有边。两点距离为欧几里得距离。每个边可以坐不同交通工具对应不同碳排放量。求起点到终点距离不超过B且碳排放量最小的路径。
题解:二维dijkstra
由于存在限制条件B,我们可以将d数组改为二维。
d [ i ] [ j ] d[i][j] d[i][j]:0点到 i 点的最小碳排放,且距离为 j 。
然后正常建边跑dijkstra即可。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
int sx, sy, tx, ty, maxdis, c[111], numc, n, x[1111], y[1111], num[1111], v[1111][1111], mod[1111][1111];
//dijkstra
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int manx = 1e3 + 5; //与n相对,对应顶点的个数
const int mamx = 5e5 + 5; //与m相对,对应边的个数
struct nod {
ll cos;
int v, dis;
nod(){}
nod(ll cos, int v, int dis):cos(cos),v(v),dis(dis){}
bool operator<(const nod& n)const {
if (cos == n.cos) return dis > n.dis;
return cos > n.cos;
}
};
priority_queue<nod> q;
struct node {
int next, v, w;
ll c;
}edge[mamx]; //边去mamx,其余取manx
bool vis[manx][manx]; //这里的标记数组与spfa的vis数组含义不同,这里标记是否入过队列
int head[manx];
ll d[manx][manx];
int k = 0;
int m, s, e; //s作为起点,e作为终点
void add(int u, int v, int w, ll c) { //链式前向星存图
edge[++k].next = head[u];
edge[k].v = v;
edge[k].w = w;
edge[k].c = c;
head[u] = k;
}
void dijkstra() {
for (int i = 0; i <= n + 1; i++) { //初始化vis d 数组
for (int j = 0; j <= maxdis; j++) {
d[i][j] = inf;
}
}
d[s][0] = 0; //s作为起点
q.push(nod(0, s, 0));
while (q.size()) {
int x = q.top().v; //取出队头
int di = q.top().dis;
q.pop();
if (vis[x][di]) continue; //如果点x访问过,跳过,访问下一个队头
vis[x][di] = 1; //访问x做标记
for (int i = head[x]; i; i = edge[i].next) {
int v = edge[i].v, w = edge[i].w;
ll cos = edge[i].c;
if (w + di > maxdis) continue;
if (d[v][w + di] > d[x][di] + cos) { //松弛操作,更新距离
d[v][w + di] = d[x][di] + cos;
//cout << d[v][w + di] << endl;
q.push(nod(d[v][w + di], v, w + di)); //把更新的距离和点入队,这里距离取负变成小根堆
}
}
}
}
int dis(int i, int j) {
return ceil(sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])));
}
int main() {
scanf("%d%d%d%d%d%d", &sx, &sy, &tx, &ty, &maxdis, &c[0]);
scanf("%d", &numc);
for (int i = 1; i <= numc; i++) scanf("%d", &c[i]);
scanf("%d", &n);
x[0] = sx, y[0] = sy;
x[n + 1] = tx, y[n + 1] = ty;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &x[i], &y[i]);
scanf("%d", &num[i]);
for (int j = 1; j <= num[i]; j++) {
scanf("%d%d", &v[i][j], &mod[i][j]);
v[i][j]++;
}
}
for (int i = 1; i <= n; i++) {
add(0, i, dis(0, i), 1ll * dis(0, i) * c[0]);
add(i, n + 1, dis(i, n + 1), 1ll * dis(i, n + 1) * c[0]);
}
add(0, n + 1, dis(0, n + 1), 1ll * dis(0, n + 1) * c[0]);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= num[i]; j++) {
add(i, v[i][j], dis(i, v[i][j]), 1ll * dis(i, v[i][j]) * c[mod[i][j]]);
add(v[i][j], i, dis(i, v[i][j]), 1ll * dis(i, v[i][j]) * c[mod[i][j]]);
}
}
s = 0;
dijkstra();
ll ans = inf;
for (int i = 0; i <= maxdis; i++) {
ans = min(ans, d[n + 1][i]);
}
printf("%lld\n", ans == inf ? -1 : ans);
return 0;
}