zoukankan      html  css  js  c++  java
  • 双指针,BFS和图论(二)

    (一)BFS

    1.地牢大师

    你现在被困在一个三维地牢中,需要找到最快脱离的出路!

    地牢由若干个单位立方体组成,其中部分不含岩石障碍可以直接通过,部分包含岩石障碍无法通过。

    向北,向南,向东,向西,向上或向下移动一个单元距离均需要一分钟。

    你不能沿对角线移动,迷宫边界都是坚硬的岩石,你不能走出边界范围。

    请问,你有可能逃脱吗?

    如果可以,需要多长时间?

    输入格式

    输入包含多组测试数据。

    每组数据第一行包含三个整数 L,R,C 分别表示地牢层数,以及每一层地牢的行数和列数。

    接下来是 L 个 R 行 C 列的字符矩阵,用来表示每一层地牢的具体状况。

    每个字符用来描述一个地牢单元的具体状况。

    其中, 充满岩石障碍的单元格用”#”表示,不含障碍的空单元格用”.”表示,你的起始位置用”S”表示,终点用”E”表示。

    每一个字符矩阵后面都会包含一个空行。

    当输入一行为”0 0 0”时,表示输入终止。

    输出格式

    每组数据输出一个结果,每个结果占一行。

    如果能够逃脱地牢,则输出”Escaped in x minute(s).”,其中X为逃脱所需最短时间。

    如果不能逃脱地牢,则输出”Trapped!”。

    数据范围

    1L,R,C100

    输入样例:

    3 4 5
    S....
    .###.
    .##..
    ###.#
    
    #####
    #####
    ##.##
    ##...
    
    #####
    #####
    #.###
    ####E
    
    1 3 3
    S##
    #E#
    ###
    
    0 0 0
    

    输出样例:

    Escaped in 11 minute(s).
    Trapped!

    解题思路:一道三维的BFS搜索题,我们可以建立三个移动数组:vx,vy,vk,分别表示北,南,东,西,上,下,设置一个三维的map数组来存储地图,
    设置一个vis数组,用来判断是否走过以及距离。
    代码:
    #include<iostream>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N=110;
    int l,r,c;
    char map[N][N][N];
    int vis[N][N][N];
    int vx[]={1,-1,0,0,0,0};
    int vy[]={0,0,1,-1,0,0};
    int vk[]={0,0,0,0,1,-1};
    typedef struct Node
    {
        int k,x,y;
    };
    bool check(int K,int X,int Y)
    {
        if(X<0||X>=r||Y<0||Y>=c||K<0||K>=l)
            return false;
        if(map[K][X][Y]=='#')
            return false;
        if(vis[K][X][Y]!=0)
            return false;
        return true;
    }
    int bfs(Node start)
    {
        queue<Node> q;
        memset(vis,0,sizeof(vis));
        q.push(start);
        while(!q.empty())
        {
            Node tem=q.front();
            if(map[tem.k][tem.x][tem.y]=='E')
                return vis[tem.k][tem.x][tem.y];
            q.pop();
            for(int i=0;i<6;i++)
            {
                int X=tem.x+vx[i];
                int Y=tem.y+vy[i];
                int K=tem.k+vk[i];
                if(check(K,X,Y)==false)
                    continue;
                vis[K][X][Y]=vis[tem.k][tem.x][tem.y]+1;
                Node t={K,X,Y};
                q.push(t);
            }
        }
        return 0;
    }
    
    int main()
    {
        int i,j,bx,by,bk,k;
        Node start;
        string ss;
        while(1)
        {
            cin>>l>>r>>c;
            if(l==0&&r==0&&c==0)
                break;
            for(k=0;k<l;k++)
            {
                for(i=0;i<r;i++)
                {
                    for(j=0;j<c;j++)
                    {
                        cin>>map[k][i][j];
                        if(map[k][i][j]=='S')
                        {
                            bk=k,bx=i,by=j;
                            start={bk,bx,by};
                        }
                    }
                }
                getline(cin,ss);
            }
        int ans=bfs(start);
        if(ans)
            cout<<"Escaped in "<<ans<<" minute(s)."<<endl;
        else
            cout<<"Trapped!"<<endl;
        }
        return 0;
    }

    2.全球变暖

    你有一张某海域 N×N 像素的照片,”.”表示海洋、”#”表示陆地,如下所示:

    .......
    .##....
    .##....
    ....##.
    ..####.
    ...###.
    .......
    

    其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 2 座岛屿。

    由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。

    具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

    例如上图中的海域未来会变成如下样子:

    .......
    .......
    .......
    .......
    ....#..
    .......
    .......
    

    请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

    输入格式

    第一行包含一个整数N。

    以下 N 行 N 列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。

    照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。

    输出格式

    一个整数表示答案。

    数据范围

    1N1000

    输入样例1:

    7
    .......
    .##....
    .##....
    ....##.
    ..####.
    ...###.
    .......
    

    输出样例1:

    1
    

    输入样例2:

    9
    .........
    .##.##...
    .#####...
    .##.##...
    .........
    .##.#....
    .#.###...
    .#..#....
    .........
    

    输出样例2:

    1
    
    解题思路:每一层的个数都是=2n-1个,而且开头的下标都是2的倍数
    代码:
    #include<iostream>
    using namespace std;
    const int N=100010;
    typedef long long ll;
    ll a[N];
    ll maxn,sum,ans;
    int main()
    {
        ll i,j,n,k;
        cin>>n;
        for(i=1;i<=n;i++)
            cin>>a[i];
        maxn=a[1];
        ans=1;
        k=1;
        for(i=2;i<=n;i=i*2)
        {
            sum=0;
            for(j=i;j<=i*2-1&&j<=n;j++)
            {
                sum+=a[j];
            }
            k++;
            if(sum>maxn)
            {
                maxn=sum;
                ans=k;
            }
        }
        cout<<ans;
        return 0;
    }
     
  • 相关阅读:
    [转载]三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法
    Java Web-EL表达式 in JSP
    MVC开发模式
    Java Web-Cookie和Session
    Java Web-JSP学习
    小知识:修改IDEA的模板
    Java Web-servlet、HTTP in servlet和捎带的Java绘图学习
    [转载]SSD原理与实现
    [转载]边框回归(Bounding Box Regression)
    jenkins添加TPS与服务器监控变化曲线图
  • 原文地址:https://www.cnblogs.com/xiaofengzai/p/12245991.html
Copyright © 2011-2022 走看看