zoukankan      html  css  js  c++  java
  • 牛客网 送外卖 BFS

    链接:https://ac.nowcoder.com/acm/problem/13224
    来源:牛客网

    题目描述

    n 个小区排成一列,编号为从 0 到 n-1 。一开始,美团外卖员在第0号小区,目标为位于第 n-1 个小区的配送站。
    给定两个整数数列 a[0]~a[n-1] 和 b[0]~b[n-1] ,在每个小区 i 里你有两种选择:
    1) 选择a:向前 a[i] 个小区。
    2) 选择b:向前 b[i] 个小区。

    把每步的选择写成一个关于字符 ‘a’ 和 ‘b’ 的字符串。求到达小区n-1的方案中,字典序最小的字符串。如果做出某个选择时,你跳出了这n个小区的范围,则这个选择不合法。
    • 当没有合法的选择序列时,输出 “No solution!”。
    • 当字典序最小的字符串无限长时,输出 “Infinity!”。
    • 否则,输出这个选择字符串。

    字典序定义如下:串s和串t,如果串 s 字典序比串 t 小,则
    • 存在整数 i ≥ -1,使得∀j,0 ≤ j ≤ i,满足s[j] = t[j] 且 s[i+1] < t[i+1]。
    • 其中,空字符 < ‘a’ < ‘b’。

    输入描述:

    输入有 3 行。
    第一行输入一个整数 n (1 ≤ n ≤ 10^5)。
    第二行输入 n 个整数,分别表示 a[i] 。
    第三行输入 n 个整数,分别表示 b[i] 。
    −n ≤ a[i], b[i] ≤ n

    输出描述:

    输出一行字符串表示答案。

    解题思路:如果用bfs从下标为0每次移动至另一状态判断是否能到达终点,其实现难点在于如何判断是否会Infinity,因为不同的走法其路线不同走过的顶点也不同;用dfs+回溯可以AC 
    参考;用bfs求解思路:反向建图,从下标n-1(实现时下标从1-n)判断是否有到达0的路径,在经过的节点上标记。接着从下标为0每次判断下一步是否在可行路径的节点上,且如果重复
    到达同一节点则Infinity。
    实现代码:
    #include<iostream>
    #include<string> 
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int Max_N = 1e5+10;
    
    int n;
    int a[Max_N], b[Max_N];
    vector<int> graph[Max_N];
    bool visited1[Max_N], visited2[Max_N]; //反向、正向经过的节点 
    
    void bfs(int s);
    void solve();
    
    int main()
    {
        cin>>n;
        for( int i=1; i<=n; i++ )
        {
            cin>>a[i];
            int x = i + a[i];
            if( 1<=x&&x<=n )    graph[x].push_back(i);//反向建图 
        }
        for( int i=1; i<=n; i++ )
        {
            cin>>b[i];
            int x = i + b[i];
            if( 1<=x&&x<=n )    graph[x].push_back(i);//反向建图 
        }
        
        solve();
        
        return 0;
    }
    
    void bfs(int s)
    {
        queue<int> que;
        que.push(s);
        visited1[s] = true; //先true在push 防止超时 
        while( !que.empty() )
        {
            int v = que.front(); que.pop();//v 当前节点 
            int cize = graph[v].size();
            for( int i=0; i<cize; i++ )
            {
                int u = graph[v][i];
                if( !visited1[u] )
                {
                    visited1[u] = true;
                    que.push(u);    //可行路径上的节点 
                }    
            }    
        }    
    }
    
    void solve()
    {
        bfs(n);
        
        if( !visited1[1] ) //没有从n到1的路径 
        {
            cout<<"No solution!"<<endl;
            return;
        }
        
        bool infinity = false;
        string ans = "";
        int x = 1;
        while( x!=n )
        {
            int nx = x + a[x];
            if( 1<=nx&&nx<=n && visited1[nx] )
            {
                if( !visited2[nx] )
                {//没有重复(环路) 
                    visited2[nx] = true;
                    ans += "a";
                    x = nx;
                }
                else//重复路径 
                    infinity = true;
            }
            else
            {
                nx = x + b[x];
                if( 1<=nx&&nx<=n && visited1[nx] )//可以走 
                {
                    if( !visited2[nx] )
                    {//没有重复(环路) 
                        visited2[nx] = true;
                        ans += "b";
                        x = nx;
                    }
                    else
                        infinity = true;
                }
            }
            if( infinity )    break;
        }
        if( infinity )    cout<<"Infinity!"<<endl;
        else            cout<<ans<<endl;
    }
  • 相关阅读:
    “XXXXX” is damaged and can’t be opened. You should move it to the Trash 解决方案
    深入浅出 eBPF 安全项目 Tracee
    Unity3d开发的知名大型游戏案例
    Unity 3D 拥有强大的编辑界面
    Unity 3D物理引擎详解
    Unity 3D图形用户界面及常用控件
    Unity 3D的视图与相应的基础操作方法
    Unity Technologies 公司开发的三维游戏制作引擎——Unity 3D
    重学计算机
    windows cmd用户操作,添加,设备管理员组,允许修改密码
  • 原文地址:https://www.cnblogs.com/w-like-code/p/14640858.html
Copyright © 2011-2022 走看看