Codeforces 1340 C (01BFS)

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);
}

猜你喜欢

转载自blog.csdn.net/qq_43653111/article/details/105799770