• 问题 F: 二师兄的纪录片(最短路或者带传送门的BFS)


    问题 F: 二师兄的纪录片

    
    
    二师兄护送师傅取经成功之后,成了名人,他决定重新把取经的路再走一遍,并且拍摄一部纪录片宣传路上的风光。

    从东土大唐到天竺的地图,是正方形的,城市坐落在 N 行 N 列的方形地图上。地图从位置(1,1)排列到位置(N,N)。地图上每一个格子是一座城市,上下左右直接相邻的城市之间可以一天到达。

    有 P 座城市住着野蛮人(野蛮城市),他们只吃红烧肉。一天三顿红烧肉,连早餐都吃红烧肉。二师兄是出家人,决定不去这些城市。

    另有 Q 座城市(友好城市)希望二师兄帮他们多宣传城市风光,所以给二师兄提供一个优惠条件:如果二师兄在这座城市(X)停留三天,就可以在第四天派专机把二师兄送到另外一座城市 Y。从城市 X 飞到城市 Y 可以瞬间完成,即:二师兄在到达X城市后,可以选择四天后到达Y城市。当然,二师兄也可以选择只在X城市停留一天,然后访问X城市直接相邻的城市。

    已知长安城位于地图的(1,1)位置,目的地灵山位于地图的 (N,N)位置。每一个友好城市只能直飞到另外一个城市。

    请求出二师兄从长安到达灵山最少需要多少天。
    
    

    输入

    输入数据第一行有三个整数,分别是 N,P,Q。
    整数之间用空格分开。城市坐标系X轴向下,起点为1,Y 轴向右,起点为1。
    数据接下来的 P 行,每行两个整数 a,b,代表某一个野蛮城市的坐标 (a,b)。
    位置信息 (a,b) 表示在 X-Y 坐标系中的位置。
    再接下来的 Q 行,每行四个整数,代表友好城市 X 的坐标和从X能直飞的城市 Y 的坐标。
    
    

    输出

    输出数据一行,表示二师兄从长安去往灵山最少需要多少天。
    如果从长安到达不了灵山,则输出-1。
    二师兄在长安出发那天记为第1天,到达灵山那天的日期就是输出数据。
    
    

    样例输入 Copy

    【样例1】
    5 7 0
    1 2
    2 4
    3 2
    3 4
    4 2
    4 4
    5 4
    【样例2】
    9 27 1 
    1 2 
    1 6 
    2 4 
    2 6 
    2 8 
    3 2 
    3 4 
    3 6 
    3 8 
    4 2 
    4 4 
    4 6 
    4 8 
    5 4 
    5 6 
    5 8 
    6 4 
    6 6 
    6 8 
    7 4 
    7 6 
    7 8 
    8 4 
    8 6 
    8 8 
    9 4 
    9 8 
    6 2 8 9
    
    

    样例输出 Copy

    【样例1】
    11
    【样例2】
    12
    
    

    提示

    样例1解释样例数据后面的解释说明当中,“.”代表可以访问的普通城市,“#”代表野蛮城市。“1”代表X城市和能从“1”直飞的城市Y。


    原地图:
    样例1原地图.png



    到达目的地的走法:



    样例2解释样例数据后面的解释说明当中,“.”代表可以访问的普通城市,“#”代表野蛮城市。“1”代表X城市和能从“1”直飞的城市Y。

    原地图:



    走法说明:走到 6 2 点的时候,穿越到 8 9 点。

    
    

     这个题就是一个带传送门的BFS但是我不会,我用最短路跑到

    跑最短路的时候就是说,把每一个点都编上号,在每一个点向四周建图

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=2e3+100;
    const int maxx=1e6+1000; 
    typedef long long ll;
    int a[maxn][maxn];
    int s[maxn][maxn];
    int n,p,q; 
    int L=0;
    struct node{
        int e,next;
        int w;
    }edge[maxx];
    int cnt=0;
    int head[maxx],vis[maxx];
    int dis[maxx];
    void add(int u,int v,int w){
        edge[cnt].e=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void di(int s){
        for(int i=0;i<=L;i++) dis[i]=INF,vis[i]=0;
        dis[s]=0;
        while(1){
            int k=-1;
            ll minl=INF;
            for(int i=1;i<=L;i++){
                if(!vis[i]&&minl>dis[i]){
                    k=i;
                    minl=dis[i];
                }
            }
            if(k==-1) break;
            vis[k]=1;
            for(int i=head[k];~i;i=edge[i].next){
                int e=edge[i].e;
                if(dis[e]>dis[k]+edge[i].w){///松弛操作 也叫更新操作
                    dis[e]=dis[k]+edge[i].w;
                }
            }
        }
    }
    int main(){
        memset(head,-1,sizeof(head));
        cin>>n>>p>>q; 
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                a[i][j]=++L;
            }
        }
        int x1,y1,x2,y2;
        for(int i=1;i<=p;i++){
            cin>>x1>>y1;
            s[x1][y1]=1;
        }
        for(int i=1;i<=q;i++){
            cin>>x1>>y1>>x2>>y2;
            add(a[x1][y1],a[x2][y2],4);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(s[i][j]==1){
                    continue;
                }
                if(i-1>=1&&s[i-1][j]!=1){
                    add(a[i][j],a[i-1][j],1);
                    add(a[i-1][j],a[i][j],1);
                }
                if(j-1>=1&&s[i][j-1]!=1){
                    add(a[i][j],a[i][j-1],1);
                    add(a[i][j-1],a[i][j],1);
                }
                if(s[i+1][j]!=1){
                    add(a[i][j],a[i+1][j],1);
                    add(a[i+1][j],a[i][j],1);
                }
                if(s[i][j+1]!=1){
                    add(a[i][j],a[i][j+1],1);
                    add(a[i][j+1],a[i][j],1); 
                }
            } 
        }
        di(1);
        if(dis[a[n][n]]!=INF)
            cout<<dis[a[n][n]]+1<<endl; 
        else{
            cout<<-1<<endl;
        }
    }
  • 相关阅读:
    iis 500
    无线密码获取
    数据库创建
    系统基础配置指令
    手把手教你用ngrx管理Angular状态
    vue中v-cloak解决刷新或者加载出现闪烁(显示变量)
    HBuilder如何与真机连接
    01 spring boot源码阅读参考
    01 git学习笔记参考
    OAuth2授权基础知识
  • 原文地址:https://www.cnblogs.com/lipu123/p/14022296.html
Copyright © 2020-2023  润新知