ACM新手DAY 5 BFS

题解

A - Oil Deposits

题目:含有油的地块称为口袋。如果两个口袋相邻,则它们是相同油藏的一部分。油沉积物可能非常大并且可能包含许多口袋。确定网格中包含多少不同的油藏。

  • BFS求连通块
  • c语言形式的输入输出有时候会很方便
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        cnt=0;
        if(n==0)///输入0 0 退出
            break;
        for(int i=0;i<n;i++)
        {
            scanf("%s",Map[i]);
        }
        ······
        printf("%d\n",cnt);
    }
    return 0;
}
  • C++形式的模板全部代码
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
const int maxn=105;
char Map[maxn][maxn];
int n,m,cnt=0;
int dir[8][2]={{1,0},{1,1},{1,-1},{-1,0},{-1,1},{-1,-1},{0,1},{0,-1}};

struct node
{
    int x;
    int y;
}now,next;

void BFS(int x,int y)
{
    now.x=x;
    now.y=y;
    Map[x][y]='*';
    queue<node> q;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int xx=now.x+dir[i][0];
            int yy=now.y+dir[i][1];
            if(xx>=0&&xx<n&&yy>=0&&y<m&&Map[xx][yy]=='@')
            {
                Map[xx][yy]='*';
                next.x=xx;
                next.y=yy;
                q.push(next);
            }
        }
    }
}

int main()
{
    while(cin>>n>>m&&n&&m)
    {
        cnt=0;
        if(n==0)
            break;
        for(int i=0;i<n;i++)
        {
            scanf("%s",Map[i]);
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(Map[i][j]=='@')
                {
                    cnt++;
                    BFS(i,j);
                }
            }
        }
        cout << cnt << endl;
    }
    return 0;
}

B - Lake Counting

题目:由于最近的降雨,水汇集在Farmer John’s田地的不同地方,其由N×M(1 <= N <= 100; 1 <= M <= 100)的正方形矩形表示。每个方块包含水(‘W’)或旱地(’。’)。农夫约翰想弄清楚他的田地里有多少个池塘。池塘是一组连接的正方形,其中有水,其中一个正方形被认为与其所有八个邻居相邻。 给出农夫约翰的田地图,确定他有多少池塘。

同样是连通块,与上一题差别很小,把判断条件改一下就好

C - Red and Black

题目:这间长方形客房铺有方形瓷砖。每个瓷砖都是红色或黑色。一个男人站在黑色的瓷砖上。从瓷砖中,他可以移动到四个相邻瓷砖中的一个。但他不能在红瓦上移动,他只能在黑色瓷砖上移动。 通过重复上述动作来计算他可以达到的黑色瓷砖的数量。

本来也是个套模板的连通块问题,就是最后一组数据总会会受到倒数第二组数据影响。回来听说是字符组的初始化问题(为什么没有被边界限制解决掉,还是不太明白。。。)。

  • BFS版本
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=105;
char Map[maxn][maxn];
int n,m,cnt=0;
int xs, ys;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
    int x, y;
} now,next;
void BFS(int x,int y)
{
    now.x=x;
    now.y=y;
    Map[x][y]='#';
    queue<node> q;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();//读取and删除第一个元素

        for(int i=0; i<4; i++)
        {
            int xx=now.x+dir[i][0];
            int yy=now.y+dir[i][1];
            if(xx>=0&&xx<n&&yy>=0&&y<m&&Map[xx][yy]=='.')
            {
                Map[xx][yy]='#';
                next.x=xx;
                next.y=yy;
                q.push(next);
                cnt++;
            }
        }
    }
}
int main()
{
    while(cin>>m>>n&&n&&m)
    {
        memset(Map, '#', sizeof Map);//初始化在这里!!!
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                cin >> Map[i][j];
                if(Map[i][j] == '@')
                {
                    xs = i; ys = j;//记录起始点
                }
            }
        cnt=1;
        BFS(xs,ys);
        cout<<cnt<<endl;
    }
    return 0;
}
  • DFS版本
#include<iostream>
using namespace std;

int m,n,cnt;
char map[105][105];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

void dfs(int x,int y)//bfs的最后一个样例让我自闭
{
    cnt++;
    map[x][y]='#';
    for(int i=0;i<4;i++)
    {
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        if(nx>=0 && nx<n && ny>=0 && ny<m && map[nx][ny]=='.')
            dfs(nx,ny);
    }
}
int main()
{
    while(cin>>m>>n && m!=0 && n!=0)
    {
        cnt=0;
        for(int i=0;i<n;i++)
            cin>>map[i];
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j] == '@')
                {
                    dfs(i,j);
                    break;
                }
            }
        }
        cout<<cnt<<endl;
    }
}

E - Catch That Cow

题目:在同一个数轴上,人在 ( N , 0 ) (N,0) N,0,牛在 ( K , 0 ) (K,0) K,0,每一次人可以选择从 ( X , 0 ) (X,0) X,0 ( X + 1 , 0 ) (X+1,0) X+1,0 ( X − 1 , 0 ) (X-1,0) X1,0 ( 2 X , 0 ) (2X,0) 2X0,求人需要多久到达牛的位置。

  • BFS求最短路。
  • BFS函数里面会有x+1,x-1,x*2三种情况的讨论。
  • BFS部分和越界判断部分
int booll(int x)//检查是否越界
{
    if(x<0 || x>=N || Map[x])
        return 0;
    return 1;
}
int bfs(int x)
{
    queue<node> q;
    now.x = x;
    now.time = 0;
    Map[x] = 1;
    q.push(now);
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        if(now.x == k)//到了就出去了
            return now.time;
        next = now;
        next.x = now.x+1;//三种情况可以设计在一个for循环里面
        if(booll(next.x))
        {
            next.time = now.time+1;
            Map[next.x] = 1;
            q.push(next);
        }
        next.x = now.x-1;
        if(booll(next.x))
        {
            next.time = now.time+1;
            Map[next.x] = 1;
            q.push(next);
        }
        next.x = now.x*2;
        if(booll(next.x))
        {
            next.time = now.time+1;
            Map[next.x] = 1;
            q.push(next);
        }
    }
    return -1;
}

G - Nightmare

题目:迷宫有一个出口,Ignatius应该在炸弹爆炸之前离开迷宫。炸弹的最初爆炸时间设定为6分钟。为了防止炸弹爆炸,Ignatius必须缓慢移动,只可以上下左右四个方向,一步需要1分钟。迷宫中的某些区域包含一个Bomb-Reset-Equipment。他们可以将爆炸时间重置为6分钟。
鉴于迷宫和Ignatius的起始位置的布局,判断Ignatius是否可以离开迷宫,如果可以的话,输出他必须用来找到迷宫出口的最短时间,否则输出-1。
以下是一些规则:
1。我们可以假设迷宫是一个2阵列。
每一分钟,伊格纳修斯只能到达最近的一个区域,他不应该走出边境,当然他也不能走在墙上。
3.如果伊格纳修斯在爆炸时间变为0时到达出口,他就无法走出迷宫。
4.当爆炸时间变为0时,如果伊格纳修斯到达包含炸弹 - 休息设备的区域,他就无法使用该设备重置炸弹。
5.炸弹重置设备可以根据需要多次使用,如果需要,Ignatius可以根据需要多次到达迷宫中的任何区域。
6.重置爆炸时间的时间可以忽略,换句话说,如果Ignatius到达包含Bomb-Rest-Equipment的区域,并且爆炸时间大于0,则爆炸时间将重置为6。

  • BFS求最短路
  • 带有特别条件的BFS最短路,还有一些剪枝的东西吧。
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
using namespace std;

const int N = 8;
const int M = 8;
char mp[N+2][M+2];
int vistime[N+2][M+2];//上次到达某点剩余的的时间
int n,m;

struct Node
{
    int x,y;
    int t,step;
}now,nextt;

int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};

int bfs(int sx,int sy)
{
    queue<Node>q;
    now.x = sx; now.y = sy;
    now.t = 6; now.step = 0;
    vistime[now.x][now.y] = 6;
    q.push(now);
    while (!q.empty())
    {
        now = q.front();
        q.pop();
        for (int i = 0;i < 4;++i)
        {

        int xx = now.x + dir[i][0];
        int yy = now.y + dir[i][1];
            if (xx>=0&&yy>=0&&xx<n&&yy<m)
            {
                nextt.x=xx;
                nextt.y=yy;
                nextt.step=now.step+1;
                nextt.t = now.t - 1;

                if (mp[nextt.x][nextt.y] == 4)
                {
                    if (6 > vistime[nextt.x][nextt.y])//避免超时
                    {
                        nextt.t = 6;
                        q.push(nextt);
                        vistime[nextt.x][nextt.y] = 6;
                    }
                    else
                        continue;
                }
                else if (mp[nextt.x][nextt.y] == 1)
                {
                    if (nextt.t == 1) continue;//下一步走到哪都是死
                    if (vistime[nextt.x][nextt.y] < nextt.t)//剪枝,上一种方法走到这里时间更少
                    {
                        q.push(nextt);
                        vistime[nextt.x][nextt.y] = nextt.t;//重置剩下的时间
                    }
                }
                else if (mp[nextt.x][nextt.y] == 3)//走到终点了
                {
                    return nextt.step;
                }
            }
        }
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int sx,sy;
        scanf("%d%d",&n,&m);
        for (int i = 0;i < n;++i)
        {
            for (int j = 0;j < m;++j)
            {
                scanf("%d",&mp[i][j]);
                if (mp[i][j] == 2)
                {
                    sx = i,sy = j;
                }
            }
        }
        memset(vistime,0,sizeof vistime);
        printf("%d\n",bfs(sx,sy));
    }
    return 0;
}

H - Knight Moves

题目:计算国际象棋中的骑士从另一个点到达一个点所需的最小移动次数。骑士可以移动的位置:
在这里插入图片描述

  • BFS求最短路
  • 简简单单套模板就好。变一下方向数组,记录一下起始位置,只调用起始位置的BFS函数就行。
  • 方向数组
int dir[8][2]= {{1,2},{2,1},{1,-2},{2,-1},{-1,2},{-2,1},{-1,-2},{-2,-1}};
  • BFS函数调用
cin >> xs >> ys >> xe >> ye ;
        if(xs == xe && ys == ye)
            cout << 0 << endl;
        else
        {memset(Map, 0, sizeof Map);
        ans=BFS(xs,ys);
        cout << ans <<endl;
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值