P1141 01迷宫 BFS

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstring>
#include<cstdio>
#define N 1001
#define LL long long
using namespace std;
bool map[N][N];
//记忆搜索
//(此处说一下,平常写广搜都会定义一个bool vis[N][N]; 然后每执行完一次广搜就会加上一句memset(vis,false,sizeof vis)来初始化,但
//这样既费时也没有太大意义,因为记忆数组remenber里就能代替它的功能,由广搜原理可知,从一个连通图并不能搜到另一个独立的
//连通图,所以只要这个记忆数组就能代替vis[N][N]的全部功能,大大节约了时间)
LL remenber[N][N]; 
 LL ans[N*N];  //储存每个联通块的大小(也就是数量)
int n, m, xxx, yyy;
LL num = 0;//表示第几个联通块
int dx[] = { 1,0,-1,0 };   
int dy[] = { 0,1,0,-1 };
struct node   //每一个节点用结构体会比较方便
{
    int x;
    int y;
    bool info; //解释一下,这个是每个节点的对应map[x][y]的值
};
LL bfs(int x, int y) //开始广搜
{
    //bool vis[N][N];
    LL sum = 0;
    queue<node>q;
    node s;
    s.x = x; s.y = y;
    sum++; num++;
    s.info = map[x][y];
    //vis[x][y] = true;
    remenber[x][y] = num;
    q.push(s);
    while (!q.empty())
    {
        node u;
        u = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            if (u.x + dx[i] < 1 || u.x + dx[i] > n || u.y + dy[i] < 1 || u.y + dy[i] > n || remenber[u.x + dx[i]][u.y + dy[i]])  //判断越界与重复
                continue;
            node t;
            t.x = u.x + dx[i]; t.y = u.y + dy[i]; t.info = map[t.x][t.y];
            if (map[u.x][u.y] != map[t.x][t.y])
            {
                remenber[t.x][t.y] = num;
                //vis[t.x][t.y] = true; //以前的错误示范,嗯对,他没用了
                sum++;
                q.push(t);
            }
        }
    }
    ans[num] = sum;
    return sum;
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)//输入输出
    {
        string s;
        cin >> s;
        for (int j = 1; j <= n; j++)
            map[i][j] = s[j - 1] - '0';
    }
    for (int i = 0; i < m; i++)
    {
        cin >> xxx >> yyy;
        if (!remenber[xxx][yyy])
        {
            cout << bfs(xxx, yyy) << endl;
            //memset(vis, false, sizeof vis);  //哈哈哈哈,以前就是这样TLE的呵呵
        }
        else
            cout << ans[remenber[xxx][yyy]] << endl;  //直接输出这个联通块对应的值
    }
    //system("pause");
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值