BFS 宽搜 B题 - Igor In the Museum

题意是一个人去参观画室,每一块空地和一个墙之间都有一幅画,给你这个人在空地的位置,他可以到处走动,问此人最多能看到多少幅画。

我说说我解这个题的过程:起初没考虑时间复杂度,直接用BFS搜索,然后TLE了,然后一看如果有10W个指令, 不超时才怪。然后想到先保存查询的状态然后查询结果就行。然后又Runtime error in test 11. 这是什么鬼错误,原来是内存溢出,检查一下原来分配点空间的时候没分配够。最后AC了。

总结了经验:出现错误有两种可能,一种是思路错了,这是致命伤,还有一种可能是非常细节的地方没考虑到,或者细微的地方考虑到了,但是打程序的时候给打错了,例如本来我要赋值呢 a = b;我写成了a == b;然后感觉对,却输不出正确的结果。很伤心的错误,再犯就剁手。


Description

Igor is in the museum and he wants to see as many pictures as possible.

Museum can be represented as a rectangular field of n × m cells. Each cell is either empty or impassable. Empty cells are marked with '.', impassable cells are marked with '*'. Every two adjacent cells of different types (one empty and one impassable) are divided by a wall containing one picture.

At the beginning Igor is in some empty cell. At every moment he can move to any empty cell that share a side with the current one.

For several starting positions you should calculate the maximum number of pictures that Igor can see. Igor is able to see the picture only if he is in the cell adjacent to the wall with this picture. Igor have a lot of time, so he will examine every picture he can see.

Input

First line of the input contains three integers n, m and k (3 ≤ n, m ≤ 1000, 1 ≤ k ≤ min(n·m, 100 000)) — the museum dimensions and the number of starting positions to process.

Each of the next n lines contains m symbols '.', '*' — the description of the museum. It is guaranteed that all border cells are impassable, so Igor can't go out from the museum.

Each of the last k lines contains two integers x and y (1 ≤ x ≤ n, 1 ≤ y ≤ m) — the row and the column of one of Igor's starting positions respectively. Rows are numbered from top to bottom, columns — from left to right. It is guaranteed that all starting positions are empty cells.

Output

Print k integers — the maximum number of pictures, that Igor can see if he starts in corresponding position.

Sample Input

Input
5 6 3
******
*..*.*
******
*....*
******
2 2
2 5
4 3
Output
6
4
10
Input
4 4 1
****
*..*
*.**
****
3 2
Output
8
 
   
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>

using namespace std;
//#define LOCAL
#define MAX_N 1005
#define INF 100000000
typedef pair<int, int> P;//点坐标

int path[1000005][3];//最多有十万个点
int px=0, fir=0;

char mus[MAX_N][MAX_N];//存放博物馆
int n, m, k;//n是高,m是宽, k是起始点
int bj[MAX_N][MAX_N];//标记点是否走过
int dir[4][2] = {1,0, 0,1, -1,0, 0,-1};

int bfs(int x, int y)
{
    int ans = 0;
    //建立队列
    queue<P> que;
    que.push(P(x,y));//起始点如队列
    fir = px;//记录每次df的第一个
    path[px][0] = x;//入队的点都记录
    path[px][1] = y;
    px++;
    bj[x][y] = 1;//标记起始点已经走过
    //进行每个点的搜索
    while(!que.empty())
    {
        //取出队列中的点
        P p = que.front();
        que.pop();//别忘了出来
        for(int i=0; i<4; i++){
            //四个方向
            int nx = p.first + dir[i][1], ny = p.second + dir[i][0];
            if(mus[nx][ny] == '.' && bj[nx][ny] == 0){
                //只有.时能走
                que.push(P(nx, ny));//点入队列
                path[px][0] = nx, path[px][1] = ny;//入队的点都标记
                px++;
                bj[nx][ny] = 1;//标记走过
            }
            else
                if(mus[nx][ny] == '*'){
                //是墙的时候
                ans++;
            }
        }
    }
    return ans;
}
int main()
{
	#ifdef LOCAL
		freopen("b:\\data.in.txt", "r", stdin);
	#endif
	while(~scanf("%d%d%d", &n, &m, &k))
    {
        px=0, fir=0;
        memset(bj, 0, sizeof(bj));//重置0
        //输入迷宫
        for(int i=0; i<n; i++)
        for(int j=0; j<m; j++){
            cin>>mus[i][j];
//            cout<<mus[i][j]<<" ";
//            if(j == m-1) cout<<endl;
        }
        //不能直接对K个点进行操作,否则会超时
        for(int i=0; i<n; i++)
        for(int j=0; j<m; j++){
            //对每一个能走的快操作
            if(mus[i][j] == '.' && bj[i][j] == 0){
                //没有检测过再dfs
                int ret = bfs(i, j);
                for(int ed=fir; ed<px; ed++){
                    path[ed][2] =  ret;//标记好点对应的结果
                }
            }
        }
        for(int i=0; i<px; i++){
            bj[ path[i][0] ][ path[i][1] ] = path[i][2];//用标记数组代替结果存储数组,实现内存节省
        }
//        for(int i=0; i<px; i++)
//            cout<<path[i][0]<<"-"<<path[i][1]<<"-"<<path[i][2]<<endl;
        int a, b;
        while(k--){
            scanf("%d%d", &a, &b);
            printf("%d\n", bj[a-1][b-1]);

        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值