zoukankan      html  css  js  c++  java
  • bfs

    题目链接:https://vjudge.net/contest/237052#problem/J

    The magical world looks like a 2-D R*C grid. Initially there are many civilizations, each civilization occupying exactly one cell. A civilization is denoted by a lowercase letter in the grid. There are also certain cells that are uninhabitable (swamps, mountains, sinkholes etc.) - these cells are denoted by a '#' in the grid. All the other cells - to which the civilizations can move  - are represented by a '.' in the grid.

    A cell is said to be adjacent to another cell if they share the same edge - in other words, for a cell (x,y), cells (x-1, y), (x, y-1), (x+1, y), (x, y+1) are adjacent, provided they are within the boundaries of the grid.   Every year each civilization will expand to all unoccupied adjacent cells. If it is already inhabited by some other civilization, it just leaves the cell alone. It is possible that two or more civilizations may move into an unoccupied cell at the same time - this will lead to a battle between the civilizations and the cell will be marked with a '*'. Note that the civilizations fighting in a particular cell do not try to expand from that cell, but will continue to expand from other cells, if possible.

    Given the initial grid, output the final state of the grid after no further expansion by any civilization is possible.

    Input (STDIN):

    The first line contains T, the number of cases. This is followed by T test case blocks.

    Each test case contains two integers, R, C.

    This is followed by R lines containing a string of length C. The j-th letter in the i-th row describes the state of the cell in year 0.

    Each cell is either a

    1. '.' which represents an unoccupied cell

    2. '#' which represents a cell that cannot be occupied

    3. A civilization represented by a lowercase letter ('a' - 'z')

    Output (STDOUT):

    For each test case, print the final grid after no expansion is possible. Apart from the notations used in the input, use '*' to denote that a battle is being waged in that particular cell. 

    Print a blank line at the end of each case.

    Constraints:

    1 <= R, C <= 500

    1 <= T <= 5

    Sample Input:

    5

    3 5

    #####

    a...b

    #####

    3 4

    ####

    a..b

    ####

    3 3

    #c#

    a.b

    #d#

    3 3

    #c#

    ...

    a.b

    3 5

    .....

    .#.#.

    a...b

    Sample Output:

    #####

    aa*bb

    #####

    ####

    aabb

    ####

    #c#

    a*b

    #d#

    #c#

    acb

    a*b

    aa*bb

    a#.#b

    aa*bb

     题目大意:输入t,t组数据,输入n,m;   n行m列,输入字符,如果字符是a~z,就是一个部落,如果是‘.',则是可以被'a~z'的部落占领的块,如果是'#',则不能被占领,每个部落向外

    扩展一个点需要一年,只能往左往右往上往下,如果两个部落在同一时间到达'.',则设置为'*',并且不能走这条路了,输出最后结果

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<cmath>
    #include<math.h>
    #include<algorithm>
    #include<set>
    #include<queue>
    typedef long long ll;
    using namespace std;
    const ll mod=1e9+7;
    #define INF 0x3f3f3f
    int n,m;
    char a[510][510];
    bool vis[510][510];
    int time1[510][510];//代表该点被到达的时间,INF为没有到达
    int dx[4]={1,0,-1,0};
    int dy[4]={0,1,0,-1};
    struct Qu
    {
        int time,x,y;//代表到达该点的时间,该点坐标
        char c;//该点字符
    };
    queue<Qu>p;//申请一个队列
    void bfs()
    {
        while(!p.empty())
        {
            Qu q=p.front();//取队头元素
            p.pop();//队头元素出队
            if(a[q.x][q.y]=='*')
                continue;
            for(int i=0;i<4;i++)
            {
                Qu s1=q;
                s1.time=q.time+1;
                s1.x=q.x+dx[i];
                s1.y=q.y+dy[i];
                if(s1.x>=0&&s1.x<n&&s1.y>=0&&s1.y<m&&time1[s1.x][s1.y]==INF&&a[s1.x][s1.y]=='.')
                {
                    a[s1.x][s1.y]=s1.c;
                    time1[s1.x][s1.y]=s1.time;
                    p.push(s1);
    
                }
                else if(s1.x>=0&&s1.x<n&&s1.y>=0&&s1.y<m&&s1.time==time1[s1.x][s1.y]&&a[s1.x][s1.y]!=s1.c)
                {
                    a[s1.x][s1.y]='*';
                }
            }
    
        }
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            //memset(vis,false,sizeof(vis));
            //在该点是否有部落
            cin>>n>>m;
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                    time1[i][j]=INF;
            }
            while(!p.empty())
                p.pop();//使得队列为空
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                {
                    cin>>a[i][j];
                    if(a[i][j]!='.'&&a[i][j]!='#')
                    {
                        Qu s;
                        s.x=i;
                        s.y=j;
                        s.c=a[i][j];
                        s.time=0;
                        p.push(s);
                        time1[i][j]=0;
                    }
                }
            }
            bfs();
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                    cout<<a[i][j];
                cout<<endl;
            }
            cout<<endl;
        }
        return 0;
    }

    题目链接:https://vjudge.net/contest/238680#problem

    Statements

    Vitaly works at the warehouse. The warehouse can be represented as a grid of n × m cells, each of which either is free or is occupied by a container. From every free cell it's possible to reach every other free cell by moving only through the cells sharing a side. Besides that, there are two robots in the warehouse. The robots are located in different free cells.

    Vitaly wants to swap the robots. Robots can move only through free cells sharing a side, moreover, they can't be in the same cell at the same time or move through each other. Find out if the swap can be done.

    Input

    The first line contains two positive integers n and m (2 ≤ n·m ≤ 200000) — the sizes of the warehouse.

    Each of the next n lines contains m characters. The j-th character of the i-th line is «.» if the corresponding cell is free, «#» if there is a container on it, «1» if it's occupied by the first robot, and «2» if it's occupied by the second robot. The characters «1» and «2» appear exactly once in these lines.

    Output

    Output «YES» (without quotes) if the robots can be swapped, and «NO» (without quotes) if that can't be done.

    Examples
    Input
    5 3

    ###

    #1#

    #.#

    #2#

    ###
    Output
    NO
    Input
    3 5

    #...#

    #1.2#

    #####
    Output
    YES


    题目大意,n行m列,但是注意数据范围1<=n*m<=200000,用二维数组会爆,所以只能用一维存二维。如果输入的是'#',则不能走,其他的可以走,要求1 2实现交换
    具体思路看代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<stdio.h>
    #include<string.h>
    #include<cmath>
    #include<math.h>
    #include<algorithm>
    #include<set>
    #include<queue>
    typedef long long ll;
    using namespace std;
    const ll mod=1e9+7;
    const int maxn=2e5+10;
    const ll maxa=32050;
    #define INF 0x3f3f3f3f3f3f
    //1和2能交换无外乎两种情况,一种就是有两条路以上,还有就是至少有一条路,但是同时在路上有一个点有三个地方可走
    char a[maxn];//题目中数据范围是n*m<=2e5,但是直接开二维会爆,所以只能用一维来存储
    int n,m,flag=0;
    int dx[4]={1,0,-1,0};
    int dy[4]={0,1,0,-1};
    bool vis[maxn];
    struct Qu
    {
        int x,y;
    };
    queue<Qu>p;//申请一个队列
    void bfs(int xx,int yy)
    {
        while(!p.empty())
        p.pop();//使得队列为空
        int sum=0;
        Qu s1,s2,s3;
        s1.x=xx;
        s1.y=yy;
        p.push(s1);
        vis[s1.x*m+s1.y]=true;//如果入队了就标记,不然的话就一直在一个点重复遍历了
        while(!p.empty())
        {
            sum=0;
            s2=p.front();//取走队头元素,同时出队
            p.pop();
            for(int i=0;i<4;i++)
            {
                int x1=s2.x+dx[i];//遍历四个方向
                int y1=s2.y+dy[i];
                if(x1>=0&&x1<n&&y1>=0&&y1<m&&a[x1*m+y1]!='#')
                {
                    sum++;//可以走的一个地方,sum++记录有多少个可以走的地方
                    s3.x=x1;
                    s3.y=y1;
                    if(!vis[x1*m+y1])
                    {
                        vis[x1*m+y1]=true;//如果未被入队,则入队,同时标记
                        p.push(s3);
                    }
    
                }
            }
            if(sum>=3)
                flag=1;
        }
    }
    int main()
    {
        memset(vis,false,sizeof(vis));
        cin>>n>>m;
        int x1,y1,x2,y2,ans=0,sum=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>a[i*m+j];
                if(a[i*m+j]=='1')
                {
                    x1=i;
                    y1=j;
                }
                else if(a[i*m+j]=='2')
                {
                    x2=i;
                    y2=j;
                }
            }
        }
        for(int i=0;i<4;i++)
        {
            memset(vis,false,sizeof(vis));
            int x3=x1+dx[i];
            int y3=y1+dy[i];
            if(x3>=0&&x3<n&&y3>=0&&y3<m&&a[x3*m+y3]!='#')
            {
                sum++;
                vis[x1*m+y1]=true;
                bfs(x3,y3);
            }
            if(vis[x2*m+y2])
                ans++;
        }
        if(sum>=3)
            flag=1;
        if(ans>=2||(ans>=1&&flag))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    Java的synchronized的同步代码块和同步方法的区别
    关于java字节码框架ASM的学习
    说说cglib动态代理
    Java虚拟机-JVM各种参数配置大全详细
    Permanent Space 和 Heap Space
    OOM三种情况
    Java性能调优(一):调优的流程和程序性能分析
    数学之路-python计算实战(17)-机器视觉-滤波去噪(中值滤波)
    使用 Pascal 脚本编写网页, PWP 项目
    android 4.0主线程訪问网络问题
  • 原文地址:https://www.cnblogs.com/caijiaming/p/9310065.html
Copyright © 2011-2022 走看看