**这道题真的把我气的......**
一开始:不就是BFS嘛!
后来:怎么0分?
再后来:T了3个!
最后:还是用记忆化BFS吧!
先讲讲最水的思路:
**一个一个格子广搜,开一个队列记录一些搜过的坐标。**
```cpp
procedure bfs(x0,y0:longint);
var dl:array[1..100000,1..2] of longint;
i,j,x,y,h,t:longint;
begin
h:=0; t:=1; dl[1,1]:=x0; dl[1,2]:=y0;
o:=1;//记录可以到几个点,别忘记了自己!
for i:=1 to n do for j:=1 to n do hash[i,j]:=false;//记录这个点是否走过,不然会死循环+答案错误
hash[x0,y0]:=true;
repeat
inc(h);
for i:=1 to 4 do
begin
x:=dx[i]+dl[h,1]; //dx、dy表示上下左右的x、y变化量
y:=dy[i]+dl[h,2];
if (map[x,y]=map[dl[h,1],dl[h,2]]) //如果与之前的数一样,不可以走,退出~
or (x=0) or (y=0) or (x=n+1) or (y=n+1)
or hash[x][y] //判断边界以及是否走过
then continue;
inc(t);
dl[t,1]:=x; dl[t,2]:=y;
hash[x,y]:=true;
inc(o);
end;
until h>=t;
end;
```
然后就华丽丽的T了3个点。。。
原来把hash赋值的时候太耗时了...
看来以后不要使用fillchar(memset)了,太费时间了
只需要在最后的时候改一下即可
for i:=1 to h do
hash[dl[i][1],dl[i][2]]:=false;
更快更省时!
然而只有80分,还有两个T!
忍无可忍的我只能用记忆化了。。。
因为题目让我们求可以跳到多少个点,所以一次BFS下来,所有队列中的点可以到达的点数都是最终求出的结果(即为o)
那么一次BFS可以顺带求出很多点的答案了。
```cpp
for i:=1 to h do begin
as[dl[i][1],dl[i][2]]:=false;
jiyi[dl[i][1],dl[i][2]]:=o;//记忆化
end;
```
完整代码如下:
```cpp
const dx:array[1..4] of longint=(0,1,0,-1);
dy:array[1..4] of longint=(-1,0,1,0);
var i,j,k,o,p,m,n,b,g,q1,q2:longint;
map,jiyi:array[0..1005,0..1005] of longint;
s:ansistring;
as:array[0..1[001,0..1001] of boolean;
procedure bfs(x0,y0:longint);
var dl:array[1..200001,1..2] of longint;
i,j,x,y,h,t:longint;
begin
h:=0; t:=1; dl[1,1]:=x0; dl[1,2]:=y0; o:=1;
as[x0,y0]:=true;
repeat
inc(h);
for i:=1 to 4 do
begin
x:=dx[i]+dl[h,1];
y:=dy[i]+dl[h,2];
if (map[x,y]=map[dl[h,1],dl[h,2]])
or (x=0) or (y=0) or (x=n+1) or (y=n+1)
```
or as[x][y]
```cpp
then continue;
inc(t);
dl[t,1]:=x; dl[t,2]:=y;
as[x,y]:=true;
inc(o);
end;
until h>=t;
for i:=1 to h do begin
as[dl[i][1],dl[i][2]]:=false;
jiyi[dl[i][1],dl[i][2]]:=o;
end;
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(s);
for j:=1 to length(s) do
map[i,j]:=ord(s[j])-48;//注意一下,这里需要字符串处理!!!
end;
for i:=1 to n do for j:=1 to n do jiyi[i,j]:=-1;
for i:=1 to m do
begin
readln(q1,q2);
if jiyi[q1,q2]<>-1 then begin writeln(jiyi[q1,q2]); continue; end;//如果这个点在之前已经(顺带)求过了,那么直接输出!
bfs(q1,q2); //广搜
writeln(o); //输出
end;
end.
```