Codeforces 1340 C Nastya and Unexpected Guest —— bfs

This way

题意:

现在有一条长度为n的街道,你要从0走到n,每个单位时间走一格,每格都有一个红绿灯。你只能朝一个方向并且每个单位时间一定要走一格,但是现在有m个岗亭,你到了岗亭时可以选择是否转向,并且在绿灯最后一秒的时候你一定要在某一个岗亭。问你最少要花多少时间到目的地。

题解:

首先这种来回走的问题一般是搜索,那么我就想到了bfs,但是有一个很重要的点:每两个岗亭之间的距离是不一样的,时间间隔不同怎么能bfs?这时候就要注意这是1维的路,也就是说没有多种选择,你每次只能往左边或者右边走,所以它可以看成m个点,组成一条链,每条边上都有一个权值,这样就可以bfs了。
那对于每个点我们需要知道这个点的位置以及到达这里时花费的绿灯的时间以及到达这里时花费的总时间。那么就是三个元素需要二维的数组来维护。
搜索最短路可以选择spfa或者dijkstra,那么dijkstra的话需要用优先队列,这里怎么优化掉这个log?可以使用双端队列,也就是如果到了红灯就放到末尾,否则放到前面,也就是将一个整个的绿灯看成权值为1,否则权值就为0,那么在队首的就是权值最小的了,对于一个绿灯内花了多少时间不用在意。

#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
#define ll long long
const int N=1e4+5,M=1e3+5;
ll dp[N][M],p[N];

int n,m;
ll g_tim,r_tim;
ll bfs(){
    ll ans=1e18;
    deque<pa>Q;
    Q.push_front({1,0});
    while(!Q.empty()){
        int u=Q.front().first,t=Q.front().second;
        Q.pop_front();
        if(p[m]-p[u]+t<=g_tim)
            ans=min(ans,dp[u][t]+p[m]-p[u]);
        int ne=u-1;
        if(ne!=0){
            int ng=t+p[u]-p[ne];
            if(ng>g_tim||~dp[ne][ng%g_tim]);
            else{
                ll ntim=dp[u][t]+p[u]-p[ne];
                if(ng==g_tim)ntim+=r_tim;
                dp[ne][ng%g_tim]=ntim;
                if(ng==g_tim)
                    Q.push_back({ne,0});
                else
                    Q.push_front({ne,ng});
            }
        }
        ne=u+1;
        if(ne<=m){
            int ng=t+p[ne]-p[u];
            if(ng>g_tim||~dp[ne][ng%g_tim]);
            else{
                ll ntim=dp[u][t]+p[ne]-p[u];
                if(ng==g_tim)ntim+=r_tim;
                dp[ne][ng%g_tim]=ntim;
                if(ng==g_tim)
                    Q.push_back({ne,0});
                else
                    Q.push_front({ne,ng});
            }
        }
    }
    if(ans<1e18)
        return ans;
    return -1;
}
int main()
{
    memset(dp,-1,sizeof(dp));
    dp[1][0]=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%lld",&p[i]);
    sort(p+1,p+1+m);
    scanf("%lld%lld",&g_tim,&r_tim);
    printf("%lld\n",bfs());
    return 0;
}
/*
15 5
0 3 7 14 15
11 11
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章