源代码:
#include<cstdio>
#include<cstring>
int m,n,Num(0),X[1000001],Y[1000001],i[1001][1001];
bool f[1001][1001],Vis[1001][1001];
int x[4]={0,0,1,-1};
int y[4]={1,-1,0,0};
bool Check(int Limit)
{
memset(X,0,sizeof(X));
memset(Y,0,sizeof(Y));
memset(Vis,0,sizeof(Vis)); //预处理。
int Head=0,Tail=1;
X[1]=1;
Y[1]=1;
Vis[1][1]=true;
while (Head<Tail) //BFS验证。
{
Head++;
int t1=X[Head];
int t2=Y[Head];
for (int a=0;a<4;a++)
{
int T1=t1+x[a];
int T2=t2+y[a];
if (T1>=1&&T1<=n&&T2>=1&&T2<=m&&!Vis[T1][T2]&&!f[T1][T2]&&i[T1][T2]>=Limit)
{
Tail++;
X[Tail]=T1;
Y[Tail]=T2;
Vis[T1][T2]=true;
if (T1==n&&T2==m)
return true;
}
}
}
return false;
}
void BFS() //BFS处理每个点到最近怪兽的距离,搜索蒟蒻的我T_T。
{
int Head=0,Tail=Num;
while (Head<Tail)
{
Head++;
int t1=X[Head];
int t2=Y[Head];
for (int a=0;a<4;a++) //只更新上下左右。
{
int T1=t1+x[a];
int T2=t2+y[a];
if (T1>=1&&T1<=n&&T2>=1&&T2<=m&&!i[T1][T2]&&!f[T1][T2])
{ //BFS是按队列顺序的,所以先找到肯定更优。
i[T1][T2]=i[t1][t2]+1;
Tail++;
X[Tail]=T1;
Y[Tail]=T2;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<=n;a++)
for (int b=1;b<=m;b++)
{
scanf("%d",&f[a][b]);
if (f[a][b])
{
X[++Num]=a; //记录怪兽节点。
Y[Num]=b;
}
}
if (f[1][1]||f[n][m]) //特判。
{
printf("0");
return 0;
}
BFS();
int Left=0,Right=m+n,Ans=0;
while (Left<=Right) //二分答案。
{
int Mid=(Left+Right)>>1;
if (Check(Mid))
{
Ans=Mid;
Left=Mid+1;
}
else
Right=Mid-1;
}
printf("%d",Ans);
return 0;
}
/*
二分答案+BFS。
先预处理出所有节点与怪兽的最短距离,然后BFS,看看能不能走到终点。
遇到想不出来的题,想想二分有没有用武之地。
搜索真是个很玄学的东西,做题还是少。
*/