传送门:https://vjudge.net/problem/Gym-102279L
题意:
给一个一维数组,从出发点sta出发,需要走到des点,有三种操作
- 向左走一步,消耗L能量
- 向右走一步,消耗R能量
- 传送,能在任意数值相同的点之间传送,每次消耗C能量
求从sta点到des点的最小能量消耗。
思路:
先离散化,再构造虚点
对于每个虚点,连接的点数字相同,即能进行传送的点
然后从起点跑一遍单源最短路即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
struct Edge {
ll to,w,next;
} e[5*maxn];
struct Node {
ll u,d;
bool operator < (const Node& b) const {
return d>b.d;
}
};
ll tot=1,n,l,r,c,sta,des;
ll a[maxn],b[maxn],dis[maxn],head[maxn];
void addEdge(ll u,ll v,ll w) {
e[tot] = (Edge) {v,w,head[u]};
head[u] = tot++;
}
//迪杰斯特拉算法跑单源最短路
void Dijkstra() {
memset(dis,0x3f,sizeof(dis));
dis[sta]=0;
priority_queue <Node> q;
q.push(Node {sta,(ll)0});
while(!q.empty()) {
Node tmp = q.top();
q.pop();
ll u=tmp.u,d=tmp.d;
for(ll i=head[u]; i; i=e[i].next) {
ll w=e[i].w,to=e[i].to;
if(dis[u]+w<dis[to]) {
dis[to] = dis[u]+w;
q.push(Node {to,dis[to]});
}
}
}
}
int main() {
cin>>n>>l>>r>>c;
cin>>sta>>des;
for(int i=1; i<=n; i++) cin>>a[i],b[i]=a[i];
//离散化
sort(b+1,b+1+n);
int sz = unique(b+1,b+1+n)-b-1;
for(int i=1; i<=n; i++) a[i]=lower_bound(b+1,b+1+sz,a[i])-b;
for(int i=1; i<=n; i++) {
if(i<n) addEdge(i,i+1,r),addEdge(i+1,i,l);
//构造虚点
addEdge(i,a[i]+n+1,c);
addEdge(a[i]+n+1,i,0);
}
//跑一遍单源最短路
Dijkstra();
cout<<dis[des]<<endl;
}