【2022牛客暑期多校训练营3】J-Journey

题意
有n个十字路口,NIO想从一段路到另一段路。NIO行驶到十字路口需选择一个方向,除了右转外都要等一次红绿灯(十字路口可以左转,右转,直行,掉头)。问NIO最少等几个红绿灯?
注意
路<a,b>和路<b,a>不同,路<a,b>指a路口->b路口,路<b,a>指b路口->a路口。如果想从路<a,b>变成路<b,a>,需要在b路口掉头一次。
做法
01最短路,dijkstra
难点在建图。
1.把每段带方向的路看成一个点,比如样例起点路<4,2>,可以看成点2,它的方向是2->4的方向而不是4->2(方便一会判断权值)。终点路<4,1>,可以看成点1,方向是1->4的方向。
2.记录每个路口的4个方向通向的路口,同时记录相连的路口之间的方向。
3.权值根据下个方向是否等于(当前点附带的方向+1)%4。等于表明是右转,权值为0;不等权值为1。
代码

#include<bits/stdc++.h>
#define PIP pair<int,pair<int,int>>
#define fi first
#define se second
using namespace std;
const int N=5e5+10,inf=0x3f3f3f3f;
int n,m,dist[N][5];
bool st[N][5];
int crs[N][5];//路口
unordered_map<int,int> dir[N];//方向
int dij(int st1, int st2, int ed1, int ed2)
{
    memset(dist, 0x3f, sizeof dist);
    dist[st2][dir[st2][st1]] = 0;
    
    priority_queue<PIP, vector<PIP>, greater<PIP>> heap;
    heap.push({0, {st2,dir[st2][st1]}});
    
    while(heap.size())
    {
        PIP t=heap.top(); heap.pop();
        int dis=t.fi, a=t.se.fi, b=t.se.se;
        //距离,点,方向
        if (st[a][b]) continue;
        st[a][b]=1;
        for(int i=0; i<4; ++i)
        {
            int tmp=(i== (b+1) % 4 ? 0 : 1);//根据方向要不要等红灯
            int v=crs[a][i];
            if(!v) continue;
            if(dist[v][dir[v][a]]>dis+tmp)
            {
                dist[v][dir[v][a]]=dis+tmp;
                heap.push({dist[v][dir[v][a]], {v, dir[v][a]}});
            }
        }
    }
 
    int res=dist[ed2][dir[ed2][ed1]];
    if (res==inf) return -1;
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<4;j++)
        {
            scanf("%d",&crs[i][j]);
            if(crs[i][j]) dir[i][crs[i][j]]=j;
        }
    }
    
    int st1, st2, ed1, ed2;
    scanf("%d%d%d%d",&st1,&st2,&ed1,&ed2);
    
    printf("%d", dij(st1,st2,ed1,ed2));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值