zoukankan      html  css  js  c++  java
  • BFS简单题记

    围成面积

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1359
    时间限制: 1000 ms         内存限制: 65536 KB
     

    【题目描述】

    编程计算由“*”号围成的下列图形的面积。面积计算方法是统计*号所围成的闭合曲线中水平线和垂直线交点的数目。如下图所示,在10*10的二维数组中,有“*”围住了15个点,因此面积为15。

     

    【输入】

    10×10的图形。

    【输出】

    输出面积。

    【输入样例】

    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 1 1 1 0 0 0
    0 0 0 0 1 0 0 1 0 0
    0 0 0 0 0 1 0 0 1 0
    0 0 1 0 0 0 1 0 1 0
    0 1 0 1 0 1 0 0 1 0
    0 1 0 0 1 1 0 1 1 0
    0 0 1 0 0 0 0 1 0 0
    0 0 0 1 1 1 1 1 0 0
    0 0 0 0 0 0 0 0 0 0
    

    【输出样例】

    15
    题解:注意可能有多个区域被圈起来
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int a[105];
    bool b[105];
    int zl[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int mp[15][15];
    struct node{
        int x,y;
        node():x(),y(){}
        node(const int x,const int y):x(x),y(y){}
    };
    queue <node>Q;
    int t=1,ans;
    void bfs(int x,int y)
    {
        mp[x][y]=++t;
        a[t]++;
        Q.push(node(x,y));
        while(!Q.empty())
        {
            node u=Q.front();
            Q.pop();
            for(int i=0;i<4;i++)
            {
                int xx=u.x+zl[i][0],yy=u.y+zl[i][1];
                if(xx>0&&xx<=10&&yy>0&&yy<=10&&!mp[xx][yy])
                {
                    mp[xx][yy]=t;
                    a[t]++;
                    Q.push(node(xx,yy));
                }
            }
        }
    }
    int main()
    {
        for(int i=1;i<=10;i++)
            for(int j=1;j<=10;j++)
                cin>>mp[i][j];
        for(int i=1;i<=10;i++)
            for(int j=1;j<=10;j++)
            if(!mp[i][j])
                bfs(i,j);
        for(int i=1;i<=10;i++)b[mp[i][1]]=1;
        for(int i=1;i<=10;i++)b[mp[i][10]]=1;
        for(int i=1;i<=10;i++)b[mp[10][i]]=1;
        for(int i=1;i<=10;i++)b[mp[1][i]]=1;
        for(int i=2;i<=9;i++)
            for(int j=2;j<=9;j++)
                if(!b[mp[i][j]]&&mp[i][j]!=1)
                {
                    b[mp[i][j]]=1;
                    ans+=a[mp[i][j]];
                }
                
        cout<<ans<<endl;
    
    }

    奇怪的电梯(lift)

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1360
    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

    【输入】

    共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。

    【输出】

    一行,即最少按键次数,若无法到达,则输出-1。

    【输入样例】

    5 1 5
    3 3 1 2 5
    

    【输出样例】

    3
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int a[205],c[205];
    bool b[205];
    int N,A,B;
    queue <int>Q;
    int bfs()
    {        
        Q.push(A);
        b[A]=1;
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            int x=u+a[u],y=u-a[u];
            if(x>0&&x<=N&&!b[x])
            {
                b[x]=1;Q.push(x);c[x]=c[u]+1;
                
            }
            if(y>0&&y<=N&&!b[y])
            {
                b[y]=1;Q.push(y);c[y]=c[u]+1;
                
            }
            if(b[B])return 1;
        }
        return 0;
    }
    int main()
    {
        cin>>N>>A>>B;
        for(int i=1;i<=N;i++)cin>>a[i];
        if(bfs())cout<<c[B]<<endl;
        else cout<<"-1"<<endl;
        
    
    }
    

    产生数(Produce)

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1361
    时间限制: 1000 ms         内存限制: 65536 KB
     

    【题目描述】

    给出一个整数n(n<=2000)和k个变换规则(k≤15)。规则:

    ① 1个数字可以变换成另1个数字;

    ② 规则中,右边的数字不能为零。

    例如:n=234,k=2规则为

    2 → 5

    3 → 6

    上面的整数234经过变换后可能产生出的整数为(包括原数)234,534,264,564共4种不同的产生数。

    求经过任意次的变换(0次或多次),能产生出多少个不同的整数。仅要求输出不同整数个数。

    【输入】

    n

    k

    x1 y1

    x2 y2

    … …

    xn yn

    【输出】

    格式为一个整数(满足条件的整数个数)。

    【输入样例】

    234
    2
    2 5
    3 6
    

    【输出样例】

    4
    题解:方案数=第1位可变化的方案*第2位可变化的方案*……*第n-1位可变化的方案*第n位可变化的方案
    
    
    
    
    复制代码
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<vector>
    using namespace std;
    int a[25];
    bool b[12];
    queue <int>Q;
    vector<int>G[15];
    int bfs(int x)
    {    
        int t=1;    
        Q.push(x);
        b[x]=1;
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            for(int i=0;i<G[u].size();i++)
            {
                int v=G[u][i];
                if(!b[v])
                {
                    t++;Q.push(v);b[v]=1;
                }
            }
        }
        return t;
    }
    int main()
    {
        string s;
        int ans=1,k;
        cin>>s>>k;
        for(int i=1;i<=k;i++)
        {
            int u,v;
            cin>>u>>v;
            G[u].push_back(v);
        }
        for(int i=0;i<s.size();i++)
            {
                memset(b,0,sizeof(b));
                ans*=bfs(s[i]-'0');
            }
        cout<<ans<<endl;    
    }

    【例8.3】最少步数

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1330
    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100*100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。

    【输入】

    A、B两点的坐标。

    【输出】

    最少步数。

    【输入样例】

    12 16
    18 10
    

    【输出样例】

    8
    9
    复制代码
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int zl[12][2]={{1,2},{1,-2},{-1,2},{-1,-2},{-2,-1},{-2,1},{2,1},{2,-1},{2,2},{-2,-2},{2,-2},{-2,2}};
    int Ax,Ay,Bx,By;
    bool mp[105][105];
    struct node{
        int x,y,step;
        node(){}
        node(const int x,const int y,const int step):x(x),y(y),step(step){}
    };
    
    int bfs(int u,int v)
    {
        queue <node>Q;
        Q.push(node(u,v,0));
        mp[u][v]=1;
        while(!Q.empty())
        {
            node nw=Q.front();
            Q.pop();
            for(int i=0;i<12;i++)
            {
                int x=nw.x+zl[i][0],y=nw.y+zl[i][1];
                if(x>0&&x<=100&&y>0&&y<=100&&!mp[x][y])
                {
                    Q.push(node(x,y,nw.step+1));
                    mp[x][y]=1;
                    if(x==1&&y==1)return nw.step+1;
                }
            }
        }
        return -1;
    }
    int main()
    {
        cin>>Ax>>Ay>>Bx>>By;
        cout<<bfs(Ax,Ay)<<endl;
        memset(mp,0,sizeof(mp));
        cout<<bfs(Bx,By)<<endl;
    }

    仙岛求药

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1251


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。

    下图 显示了一个迷阵的样例及李逍遥找到仙药的路线。

    【输入】

    输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义:

    1)‘@’:少年李逍遥所在的位置;

    2)‘.’:可以安全通行的方格;

    3)‘#’:有怪物的方格;

    4)‘*’:仙药所在位置。

    当在一行中读入的是两个零时,表示输入结束。

     

    【输出】

    对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。

    【输入样例】

    8 8
    .@##...#
    #....#.#
    #.#.##..
    ..#.###.
    #.#...#.
    ..###.#.
    ...#.*..
    .#...###
    6 5
    .*.#.
    .#...
    ..##.
    .....
    .#...
    ....@
    9 6
    
    .#..#.
    .#.*.#
    .####.
    ..#...
    ..#...
    ..#...
    ..#...
    #.@.##
    .#..#.
    0 0

    【输出样例】

    10
    8
    -1
    复制代码
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    int qx,qy,m,n;
    const int zl[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    char mp[25][25];
    struct node{
        int x,y,step;
        node():x(),y(),step(){}
        node(const int x,const int y,const int step):x(x),y(y),step(step){}
    };
    void bfs()
    {
        queue <node> Q;
        Q.push(node(qx,qy,0));
        mp[qx][qy]='#';
        while(!Q.empty())
        {
            node nw=Q.front();
            Q.pop();
            for(int i=0;i<4;i++)
            {
                int x1=nw.x+zl[i][0],yy1=nw.y+zl[i][1];
                if(x1>=0&&x1<m&&yy1>=0&&yy1<n&&(mp[x1][yy1]=='*'||mp[x1][yy1]=='.'))
                {
                    if(mp[x1][yy1]=='*')
                    {
                        cout<<nw.step+1<<endl;
                        return ;
                    }
                    Q.push(node(x1,yy1,nw.step+1));
                    mp[x1][yy1]='#';
                }
            }
            
        }
        cout<<"-1"<<endl;
    }
    int main()
    {
        
        while(cin>>m>>n)
        {
            if(!m&&!n)break;
            for(int i=0;i<m;i++)
            {
                scanf("%s",mp[i]);
                for(int j=0;j<n;j++)
                    if(mp[i][j]=='@')
                    {
                        qx=i;qy=j;
                    }
            }
            bfs();
        }
    }

    Dungeon Master

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1248


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    这题是一个三维的迷宫题目,其中用‘.’表示空地,‘#’表示障碍物,‘S’表示起点,‘E’表示终点,求从起点到终点的最小移动次数,解法和二维的类似,只是在行动时除了东南西北移动外还多了上下。可以上下左右前后移动,每次都只能移到相邻的空位,每次需要花费一分钟,求从起点到终点最少要多久。

    【输入】

    多组测试数据。

    一组测试测试数据表示一个三维迷宫:

    前三个数,分别表示层数、一个面的长和宽,后面是每层的平面图。前三个数据为三个零表示结束。

    【输出】

    最小移动次数。

    【输入样例】

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

    【输出样例】

    Escaped in 11 minute(s).
    Trapped!

    【提示】

    对于题目给出数据的含义就是输入l,r,c,分别代表迷宫有l层,每层长宽分别是c,r。对于数据以可以这样移动:

     (1,1,1)->(1,1,2)->(1,1,3)->(1,1,4)->(1,1,5)->(1,2,5)->

     (1,3,5)->(1,3,4)->(1,4,4)->(2,4,4)->(2,4,5)->(3,4,,5)

     共11步就可以到达终点 对于数据二明显不能到达,则输出Trapped!

     这题用BFS解,每次去队首元素,如果是终点则输出结果移动的次数,否则,从该点开始分别向东南西北上下移动(如果可以走的话)并继续搜,如果到队列为空还没搜到解法,则说明无解。

    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int L,r,c,qx,qy,qz;
    const int maxn=105;
    char mp[maxn][maxn][maxn];
    int x1[7]={0,0,0,0,1,-1};
    int y1[7]={1,-1,0,0,0,0};
    int z1[7]={0,0,1,-1,0,0};
    struct node
    {
       int z,x,y,step;
       node ():z(),x(),y(),step(){}
       node (const int z,const int x,const int y,const int step):z(z),x(x),y(y),step(step){}
    };
    void bfs()
    {
        queue <node>Q;
        Q.push(node(qz,qx,qy,0));
        mp[qz][qx][qy]='#';
        while(!Q.empty())
        {
            node nw=Q.front();
            Q.pop();        
            for(int i=0;i<7;i++)
            {
                int zn=nw.z+z1[i],xn=nw.x+x1[i],yy1=nw.y+y1[i];
                if(zn>=0&&zn<L&&xn>=0&&xn<r&&yy1>=0&&yy1<c&&(mp[zn][xn][yy1]=='.'||mp[zn][xn][yy1]=='E'))
                {
                    if(mp[zn][xn][yy1]=='E')
                    {
                        printf("Escaped in %d minute(s).
    ",nw.step+1);
                        return ;
                    }
                    Q.push(node(zn,xn,yy1,nw.step+1));
                    mp[zn][xn][yy1]='#';
                }
            }
        }
        cout<<"Trapped!"<<endl;
    }
    int main()
    {
        
        while(cin>>L>>r>>c)
        {
            
            if(r==0&&L==0&&c==0)break;
            memset(mp,0,sizeof(mp));
            char a;        
            for(int i=0;i<L;i++)
                for(int j=0;j<r;j++)
                {
                    scanf("%s",mp[i][j]);
                    for(int m=0;m<c;m++)
                        if(mp[i][j][m]=='S')
                        {
                            qz=i;qx=j;qy=m;
                        }    
                }
            bfs();    
                    
        }
    }

    Knight Moves

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1257


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    输入n代表有个n*n的棋盘,输入开始位置的坐标和结束位置的坐标,问一个骑士朝棋盘的八个方向走马字步,从开始坐标到结束坐标可以经过多少步。

    【输入】

    首先输入一个n,表示测试样例的个数。

    每个测试样例有三行。

    第一行是棋盘的大小L(4<=L<=300);

    第二行和第三行分别表示马的起始位置和目标位置(0~L-1)。

     

    【输出】

    马移动的最小步数,起始位置和目标位置相同时输出0。

    【输入样例】

    3
    8
    0 0
    7 0
    100
    0 0
    30 50
    10
    1 1
    1 1

    【输出样例】

    5
    28
    0
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int n,qx,qy,ex,ey;
    int a[8][2]={{1,2},{-1,2},{-2,1},{2,1},{-1,-2},{1,-2},{-2,-1},{2,-1}};
    int mp[305][305];
    struct node
    {
       int x,y,step;
       node ():x(),y(),step(){}
       node (const int x,const int y,const int step):x(x),y(y),step(step){}
    };
    void bfs()
    {
        queue <node>Q;
        Q.push(node(qx,qy,0));
        mp[qx][qy]=-1;
        while(!Q.empty())
        {
            node nw=Q.front();
            Q.pop();        
            for(int i=0;i<8;i++)
            {
                int xn=nw.x+a[i][0],yy1=nw.y+a[i][1];
                if(xn>=0&&xn<n&&yy1>=0&&yy1<n&&mp[xn][yy1]==0)
                {
                    if(xn==ex&&yy1==ey)
                    {
                        printf("%d
    ",nw.step+1);
                        return ;
                    }
                    Q.push(node(xn,yy1,nw.step+1));
                    mp[xn][yy1]=-1;
                }
            }
        }
        cout<<"0"<<endl;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            cin>>n;
            cin>>qx>>qy>>ex>>ey;
            if(qx==ex&&qy==ey)
            {
                cout<<"0"<<endl;return 0;
            }        
            memset(mp,0,sizeof(mp));
            bfs();    
                    
        }
    }

    抓住那头牛

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1253


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:

    1、从X移动到X-1或X+1,每次移动花费一分钟

    2、从X移动到2*X,每次移动花费一分钟

    假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

    【输入】

    两个整数,N和K。

    【输出】

    一个整数,农夫抓到牛所要花费的最小分钟数。

    【输入样例】

    5 17

    【输出样例】

    4
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int zl[3]={1,-1},m[1000006];
    int n,k;
    void bfs()
    {
        queue <int>Q;
        Q.push(n);
        while(!Q.empty())
        {
            int x=Q.front();
            Q.pop();
            for(int i=0;i<3;i++)
            {
                int x1;
                if(i==2)x1=2*x;
                else x1=x+zl[i];
                if(x1>=0&&x1<=100005&&!m[x1])
                {
                    if(x1==k)
                    {
                        cout<<m[x]<<endl;return ;
                    }
                    m[x1]=m[x]+1;
                    Q.push(x1);
                }
            
            }
        }
        
    }
    int main()
    {
    
        cin>>n>>k;
        m[n]=1;
        bfs();
    }

    The Castle

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1250


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    一座城堡被分成m*n个方块(m≤50,n≤50),每个方块可有0~4堵墙(0表示无墙)。下面示出了建筑平面图:

    图中的加粗黑线代表墙。几个连通的方块组成房间,房间与房间之间一定是用黑线(墙)隔开的。

    现在要求你编一个程序,解决以下2个问题:

    1、该城堡中有多少个房间?

    2、最大的房间有多大?

     

    【输入】

    平面图用一个数字表示一个方块(第1个房间用二进制1011表示,0表示无东墙,用十进制11表示)。

    第一行一个整数m(m≤50),表示房子南北方向的长度。

    第二行一个整数n(n≤50),表示房子东西方向的长度。

    后面的m行,每行有n个整数,每个整数都表示平面图对应位置的方块的特征。每个方块中墙的特征由数字P来描述(0≤P≤15)。数字P是下面的可能取的数字之和:

    1(西墙 west)

    2(北墙 north)

    4(东墙 east)

    8(南墙 south)

    室内的墙被定义两次: 例如方块(1,1)中的南墙也被位于其南面的方块(2,1)定义了一次。

    建筑中至少有两个房间。

     

    【输出】

    第1行:一个整数,表示房间总数;

    第2行:一个整数,表示最大房间的面积(方块数)。

     

    【输入样例】

    4
    7
    11 6 11  6  3 10  6
    7  9  6 13  5 15  5
    1 10 12  7 13  7  5
    13 11 10 8 10 12 13
    

    【输出样例】

    5
    9
    题解:mp[i][j][0]记录是第几个房间,mp[i][j][1..4]记录该方向是否有障碍
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,m,ans;
    int mp[255][255][6];
    struct node{
        int x,y;
        node():x(),y(){}
        node(const int x,const int y):x(x),y(y){}
    };
    int zl[5][2]={{0},{0,-1},{-1,0},{0,1},{1,0}};
    int a[5]={0,1,2,4,8};
    void bfs(int x,int y,int t)
    {
        queue <node>Q;
        Q.push(node(x,y));
        ans++;
        mp[x][y][0]=t;
        while(!Q.empty())
        {
            node nw=Q.front();
            Q.pop();
            for(int i=1;i<=4;i++)
            {
                int x1=nw.x+zl[i][0],yy1=nw.y+zl[i][1];
                if(x1>0&&x1<=m&&yy1>0&&yy1<=n&&!mp[nw.x][nw.y][i]&&!mp[x1][yy1][0])
                {
                    mp[x1][yy1][0]=t;
                    Q.push(node(x1,yy1));
                    ans++;
                }
            }
        }
        
    }
    int main()
    {
    
        cin>>m>>n;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                int p;
                cin>>p;
                for(int k=4;k>0;k--)
                    if(p-a[k]>=0)
                    {
                        p-=a[k];
                        mp[i][j][k]=1;
                    }
            }
        int t=1,maxn=0;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            if(!mp[i][j][0])
            {
                bfs(i,j,t++);
                maxn=max(maxn,ans);
                ans=0;
            }
        
        cout<<t-1<<endl<<maxn<<endl;
    }
    
    

    Lake Counting

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1249


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    题意:有一块N*M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?

    【输入】

    第一行为N,M(1<=N,M<=110)。

    下面为N*M的土地示意图。

    【输出】

    一行,共有的水洼数。

    【输入样例】

    10 12
    W........WW.
    .WWW.....WWW
    ....WW...WW.
    .........WW.
    .........W..
    ..W......W..
    .W.W.....WW.
    W.W.W.....W.
    .W.W......W.
    ..W.......W.

    【输出样例】

    3
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,m;
    int mp[115][115];
    queue <int> Q;
    int a[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,-1},{-1,1},{-1,-1},{1,1}};
    //包括斜的
    void bfs(int k)
    {
        while(!Q.empty())
        {
            int x=Q.front();Q.pop();
            int y=Q.front();Q.pop();
            for(int i=0;i<8;i++)
            {
                int x1=x+a[i][0];
                int yy1=y+a[i][1];
                if(x1>0&&x1<=n&&yy1>0&&yy1<=m&&mp[x1][yy1]==0)
                    {
                        Q.push(x1);Q.push(yy1);
                        mp[x1][yy1]=k;
                    }                
            }
        }
    }
    
    int main()
    {
        int ans=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                char a;
                cin>>a;
                if(a=='.')mp[i][j]=-1;
            }
        int k=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(!mp[i][j])
                {
                    Q.push(i);Q.push(j);
                    mp[i][j]=++k;
                    bfs(k);
                    
                }
                
            }
        cout<<k<<endl;    
    }
     

    迷宫问题

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1255


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    定义一个二维数组:

    int maze[5][5] = {

    0,1,0,0,0,

    0,1,0,1,0,

    0,0,0,0,0,

    0,1,1,1,0,

    0,0,0,1,0,

    };

    它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

     

    【输入】

    一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

    【输出】

    左上角到右下角的最短路径,格式如样例所示。

    【输入样例】

    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0

    【输出样例】

    (0, 0)
    (1, 0)
    (2, 0)
    (2, 1)
    (2, 2)
    (2, 3)
    (2, 4)
    (3, 4)
    (4, 4)
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    queue <int> Q;
    int a[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int mp[6][6];
    int j[6][6][2];
    int bfs()
    {
        int flag=0;
        while(!Q.empty())
        {
            if(flag)return 0;
            int x=Q.front();Q.pop();
            int y=Q.front();Q.pop();
            for(int i=0;i<4;i++)
            {
                int x1=x+a[i][0],yy1=y+a[i][1];
                if(x1>0&&x1<6&&yy1>0&&yy1<6&&!mp[x1][yy1])
                {
                    mp[x1][yy1]=mp[x][y]+1;
                    j[x1][yy1][0]=x;j[x1][yy1][1]=y;
                    if(x1==5&&yy1==5){
                        flag=1;break;
                    }
                    Q.push(x1);Q.push(yy1);
                }
            }
        }
    }
    int show(int x,int y)
    {
        if(x==1&&y==1)return 0;
        show(j[x][y][0],j[x][y][1]);
        printf("(%d, %d)
    ",j[x][y][0]-1,j[x][y][1]-1);
            
    }
    int main()
    {
        for(int i=1;i<6;i++)
            for(int j=1;j<6;j++)
                {
                    cin>>mp[i][j];
                    if(mp[i][j])mp[i][j]=-1;
                }
        Q.push(1);Q.push(1);
        mp[1][1]=1;
        bfs();
        
        show(5,5);
        printf("(4, 4)
    ");
    }
    
    

    流感传染

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1191
    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    有一批易感人群住在网格状的宿舍区内,宿舍区为n*n的矩阵,每个格点为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人得了流感,以后每天,得流感的人会使其邻居传染上流感,(已经得病的不变),空房间不会传染。请输出第m天得流感的人数。

    【输入】

    第一行一个数字n,n不超过100,表示有n*n的宿舍房间。

    接下来的n行,每行n个字符,’.’表示第一天该房间住着健康的人,’#’表示该房间空着,’@’表示第一天该房间住着得流感的人。

    接下来的一行是一个整数m,m不超过100。

    【输出】

    输出第m天,得流感的人数。

    【输入样例】

    5
    ....#
    .#.@.
    .#@..
    #....
    .....
    4
    

    【输出样例】

    16
    复制代码
    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<queue>
    using namespace std;
    struct node{
        int x,y,num;
    };
    queue <node> Q;
    char a[105][105];
    int mp[105][105];
    int p[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
    int n,t;
    void dfs(int t){
        while(!Q.empty())
        {
            node now=Q.front();Q.pop();
            for(int i=0;i<4;i++)
            {    
                node s;
                s.x=now.x+p[i][0];
                s.y=now.y+p[i][1];
                s.num=now.num+1;
                if(s.num>t)return;
                if(s.x>0&&s.x<=n&&s.y>0&&s.y<=n&&mp[s.x][s.y]==0)
                {
                    mp[s.x][s.y]=1;
                    Q.push(s);
                }
            }
        }
    }
    int main()
    {
        int cnt=0,k=0;
        cin>>n;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                cin>>a[i][j];
                if(a[i][j]=='#')mp[i][j]=-1;
                if(a[i][j]=='@')
                {
                    mp[i][j]=1;
                    node s;
                    s.x=i;s.y=j;s.num=1;
                    Q.push(s);
                    
                }
                
            }
        
        cin>>t;
        dfs(t);    
    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(mp[i][j]==1)cnt++;
        cout<<cnt<<endl;
    }
    3411 洪水
    链接:http://codevs.cn/problem/3411/
    题目描述 Description

    小浣熊松松和朋友到野外露营,没想到遇上了&pi;年一次的大洪水,好在松松是一只爱观察的小浣熊,他发现露营地的地形和洪水有如下性质:

    ①露营地可以被看做是一个N*M的矩形方阵,其中左上角坐标为(1,1),右下角坐标为(n,m),每个格子(i,j)都有一个高度h(i,j)。

    ②洪水送(r,c)开始,如果一个格子被洪水淹没,那这个格子四周比它低(或相同)的格子也会被淹没。

    现在松松想请你帮忙算算,有多少个格子不会被淹没,便于他和朋友逃脱。

    【原有误数据已删除】

    输入描述 Input Description

    第一行包含两个整数n,m,表示矩形方阵右下角坐标。

    以下n行,每行m个数,第i行第j个数表示格子(i,j)的高度。

    最后一行包含两个整数r,c,表示最初被洪水淹没的格子。

    输出描述 Output Description

    输出仅一行,为永远不会被淹没的格子的数量。

    样例输入 Sample Input

    3 3

    1 2 3

    2 3 4

    3 4 5

    2 2

    样例输出 Sample Output

    5

    数据范围及提示 Data Size & Hint

    对于90%的数据,保证随机生成。

    对于100%的数据,1<=N,M<=1000。

    题解:向四个方位漫搠,访问了就做标记

    复制代码
    #include<bits/stdc++.h>
    using namespace std;
    int N,M;
    int h[1005][1005],mp[1005][1005]; 
    int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    void bfs(int r,int c){
        mp[r][c]=1;
        for(int i=0;i<4;i++){
            int x=r+f[i][0];int y=c+f[i][1];
            //cout<<x<<" "<<y<<" "<<h[x][y]<<"B"<<endl;    
            if(x>=1&&x<=N&&y>=1&&y<=M){
                
                if(mp[x][y])continue;
                if(h[x][y]<=h[r][c]){
                    bfs(x,y);
                
                }
            }
        }
        
    }
    int main(){
        int r,t,cnt=0;
        cin>>N>>M;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)scanf("%d",&h[i][j]);
        scanf("%d%d",&r,&t);
        bfs(r,t);
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
                if(mp[i][j]==0)cnt++;
                
            
                
        printf("%d
    ",cnt);
    }
     



  • 相关阅读:
    yii---where or该如何使用
    yii---获取当前sql语句
    yii---load怎么使用
    yii---往对象里面添加属性
    js---箭头函数
    yii---判断POST请求
    Atitit USRqc62204 证书管理器标准化规范
    Atitit  深入理解命名空间namespace  java c# php js
    atitit..代码生成流程图 流程图绘制解决方案 java  c#.net  php v2
    Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8017901.html
Copyright © 2011-2022 走看看