思路
见题意,由于每次只向四个方向尝试移动,所以可采用深搜(状态为坐标)。
然而数据规模中,n<=1000,m<=100000,如果每次输入坐标时重新走一次将会超时。
再想想,每一次搜索会找到一个区块,该区块中所有点的答案都相同,所以,答案可以存在一个数组里——
题目每给出一个坐标,先判断该坐标是否已有答案(通过前面已给出的点搜索获得的),是则直接输出,否则深搜:先重置pl,为了将该点所属区块都染上色(不能在深搜内部染色,因为过程中并不知道区域内到底有多少连通点),在一趟深搜过程中,每到一个新的点就++pl,并将该点的坐标存在临时数组里,搜索结束后再依据坐标数组把答案数组的对应位置填上pl。
//my ac code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int n,ans,m;
int ng[1005][1005];
int nn[1005][1005];
int jg[1000005][2];
int x[4]={1,0,-1,0};
int y[4]={0,-1,0,1};
void dfs(int a,int b){
ans++;
jg[ans][0]=a;
jg[ans][1]=b;
nn[a][b]=1;
for(int i=0;i<4;i++){
int xa=a+x[i];int ya=b+y[i];
if(xa<1||xa>n||ya<1||ya>n)continue;
if(nn[xa][ya]>0)continue;
if(ng[a][b]==ng[xa][ya])continue;
dfs(xa,ya);
}
}
int main(){
scanf("%d%d",&n,&m);
//printf("%d%d",n,m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%1d",&ng[i][j]);
//printf("%1d",ng[i][j]);
}
//printf("\n");
}
for(int i=1;i<=m;i++){
ans=0;
int tx,ty;
scanf("%d%d",&tx,&ty);
if(nn[tx][ty]>0){
printf("%d\n",nn[tx][ty]);
continue;
}
dfs(tx,ty);
for(int j=1;j<=ans;j++)
nn[jg[j][0]][jg[j][1]]=ans;
printf("%d\n",ans);
}
return 0;
}