#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=1010,M=0,Z=1e9+7,ms63=1061109567;
const int dy[4]={-1,0,0,1};
const int dx[4]={0,-1,1,0};
int casenum,casei;
char a[N][N];
int vis[N][N];
int rec[N*N];
int ans[N][N];
int n,m,q,tim,num;
void dfs(int y,int x)
{
vis[y][x]=tim;
for(int i=0;i<4;i++)
{
int yy=y+dy[i];
int xx=x+dx[i];
if(a[yy][xx]=='*')++num;
else if(!vis[yy][xx])dfs(yy,xx);
}
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&q))
{
MS(vis,0);
tim=0;
for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)if(a[i][j]=='.')
{
if(vis[i][j]==0)
{
++tim;
num=0;
dfs(i,j);
rec[tim]=num;
}
ans[i][j]=rec[vis[i][j]];
}
}
int y,x;
while(q--)
{
scanf("%d%d",&y,&x);
printf("%d\n",ans[y][x]);
}
}
return 0;
}
/*
【题意】
给你一个n(1000)*m(1000)的地图,有k(1e5)个询问,地图上的'*'代表墙,'.'代表空地。
一个墙最多有4个面。*与.相邻的就是其一个面。
对于每个询问,给出一个范围内的坐标(y,x),问你,从这个开始向四周走,能撞到多少面墙。
【类型】
简单dfs
【分析】
直接从每个'.'开始dfs,dfs到的'.'都打上同样的标记,表示其为是相同联通块,
相同连通块的答案是相同的。
同时对墙的每一面用bool数组打标记,被第一次搜到的话就用全局变量计数++
这个全局变量用来更新这个联通块的答案。
这样这道题就做完啦。
然后我们发现,
因为每个'.'最多走一次,
所以其实每面墙也只最多计数1次,它最多只会对一个联通块的答案贡献1.
【时间复杂度&&优化】
O(4nm)
*/
【Educational Codeforces Round 1D】【DFS 联通块打标记法】Igor In the Museum 联通块内墙的面数
最新推荐文章于 2019-07-28 09:54:28 发布