所谓01bfs就是在bfs的时候,用一个dequeue把权值增加了的点放到队列后面,权值不增加的放到前面。这样就可以保证拿出来的点权值是递增的,就可以不用优先队列了。
这样优化之后,原来
O
(
n
l
o
g
m
)
O(nlogm)
O(nlogm)的问题就可以转化为
O
(
n
)
O(n)
O(n)的问题。(如迪杰斯特拉求最短路)
对于这道题,01bfs的时候,将一次红绿灯看作1,记录一下
v
i
s
[
i
]
[
t
vis[i][t%k]
vis[i][t即可保证复杂度是
O
(
m
∗
g
)
O(m*g)
O(m∗g)。
很多人场上直接spfa或bfs过了,fst时候t掉了。
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int a[MXN],g,r,n,m;
int vis[10004][1005];
struct no{
int v,t,tt;
};
int _01bfs(){
deque<no>q;
q.push_front(no{1,0,0});
vis[1][0]=1;
int ans=INT_MAX;
while(!q.empty()){
int now=q.front().v,ti=q.front().t,mt=q.front().tt;
q.pop_front();
int ddd=a[m]-a[now];
int hhh=g-mt;
if(hhh>=ddd) ans=min(ans,ti+ddd);
if(now!=1){
int dis=a[now]-a[now-1];
int have=g-mt;
if(dis<have&&vis[now-1][mt+dis]==0){
vis[now-1][mt+dis]=1;
q.push_front(no{now-1,ti+dis,mt+dis});
}
else if(dis==have&&vis[now-1][0]==0){
vis[now-1][0]=1;
q.push_back(no{now-1,ti+dis+r,0});
}
}
if(now!=m){
int dis=-a[now]+a[now+1];
int have=g-mt;
if(dis<have&&vis[now+1][mt+dis]==0){
vis[now+1][mt+dis]=1;
q.push_front(no{now+1,ti+dis,mt+dis});
}
else if(dis==have&&vis[now+1][0]==0){
vis[now+1][0]=1;
q.push_back(no{now+1,ti+dis+r,0});
}
}
}
return ans;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++)scanf("%d",&a[i]);
cin>>g>>r;
sort(a+1,a+1+m);
int ans=_01bfs();
if(ans==INT_MAX)ans=-1;
cout<<ans<<'\n';
return 0;
}