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;
    }
  • 相关阅读:
    ASP.NET中的状态保持(转载)
    Win7系统下VS2008安装SP1补丁解决JQuery无智能提示的问题
    合并多个List<T>类型并通过LINQ按指定属性排序
    ASP.NET状态保持:ViewState
    第一部分 CLR基础:第1章 CLR的执行模型
    Oracle存储过程知识汇总
    ASP.NET中Button控件的CommandName和CommandArgument属性用法
    PL/SQL Developer使用
    ASP.NET常用代码汇总
    PL/SQL Developer中文注释乱码的解决办法
  • 原文地址:https://www.cnblogs.com/w-like-code/p/14640858.html
Copyright © 2011-2022 走看看