Codeforces 1340 C (01BFS)
题意:你要从0走到n,红绿灯交替,绿灯可以随便走,只有红灯只能呆在安全岛上而且不能动,给你m个安全岛的位置,只有在安全岛上可以往后走或者往前走,问你从0—n的最短时间。
思路:n * m * log会超时,不能像最短路那样转移。注意到红灯这一段时间我们什么也不能做,我们只能呆在岛上,那么我们可不可以把g+r看成一段时间呢?
我们假设dp[i][j]表示当前走到第i个点只剩j时间的绿灯了,那么当前可以向前或者先后走,边权是0或者1,用deque就行。
/*
▄███████▀▀▀▀▀▀███████▄
░▐████▀▒▒▒▒▒▒▒▒▒▒▀██████▄
░███▀▒▒▒ACCEPTED▒▒▒▒▀█████
░▐██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░▐█▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░░█▒▄▀▀▀▀▀▄▒▒▄▀▀▀▀▀▄▒▐███▌
░░░▐░░░▄▄░░▌▐░░░▄▄░░▌▐███▌
░▄▀▌░░░▀▀░░▌▐░░░▀▀░░▌▒▀▒█▌
░▌▒▀▄░░░░▄▀▒▒▀▄░░░▄▀▒▒▄▀▒▌
░▀▄▐▒▀▀▀▀▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒█
░░░▀▌▒▄██▄▄▄▄████▄▒▒▒▒█▀
░░░░▄██████████████▒▒▐▌
░░░▀███▀▀████▀█████▀▒▌
░░░░░▌▒▒▒▄▒▒▒▄▒▒▒▒▒▒▐
░░░░░▌▒▒▒▒▀▀▀▒▒▒▒▒▒▒▐
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
const int M = 1e4 + 5;
const int INF=1e9+7;
const int mod=998244353;
typedef long long ll;
typedef pair<int,int>p;
int dp[M][N],x[M],g,r,n,m;
int main() {
ll ans=1e18;
memset(dp,63,sizeof dp);
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
scanf("%d",&x[i]);
sort(x+1,x+m+1);
scanf("%d%d",&g,&r);
deque<p>q;
q.push_back({
1,g});
dp[1][g]=0;
while(!q.empty()) {
int cur=q.front().first;
int res=q.front().second;
q.pop_front();
if(cur>=2) {
int dis=x[cur]-x[cur-1];
if(dis<res) {
if(dp[cur-1][res-dis]>dp[cur][res]) {
dp[cur-1][res-dis]=dp[cur][res];
q.push_front({
cur-1,res-dis});
}
} else if(dis==res) {
if(dp[cur-1][g]>dp[cur][res]+1) {
dp[cur-1][g]=dp[cur][res]+1;
q.push_back({
cur-1,g});
}
}
}
if(cur<=m-1) {
int dis=x[cur+1]-x[cur];
if(dis<res) {
if(dp[cur+1][res-dis]>dp[cur][res]) {
dp[cur+1][res-dis]=dp[cur][res];
q.push_front({
cur+1,res-dis});
}
} else if(dis==res) {
if(dp[cur+1][g]>dp[cur][res]+1) {
dp[cur+1][g]=dp[cur][res]+1;
q.push_back({
cur+1,g});
}
}
}
}
for(int i=1; i<=m; i++) {
if(dp[i][g]<1e9&&n-x[i]<=g)
ans=min(ans,1ll*dp[i][g]*(r+g)+n-x[i]);
}
if(ans==1e18)
ans=-1;
printf("%lld\n",ans);
}