一道比较有思维难度的广搜题。
每一个时刻会有一个岛屿发生移动,求最快多长时间能到目标点,很容易想到广搜。
首先将起点BFS一次,标记出所有能到的点,如果此时已经能到目标点了,直接输出0就行了。
然后对于每一个时刻,有一个岛移动了,考虑这个移动有哪些情况。
1.移动的这个岛恰好是之间标记过的岛,也就是可以从这个岛出发,这次移动之后,要把这个点BFS一遍。把能到达的岛标记出来。
2.移动的这个岛是之前没标记过的岛,也就是即使可以从这个岛出发走到终点,现在也没法走,因为之前没有上过这个岛。
所以只有这个岛和之前标记过的岛连到一起才可能拓展出更多的岛,也就是把这个点BFS一遍,只有存在恰好有跟它相邻且标记过的岛才能满足继续拓展的条件。
#include<bits/stdc++.h>
using namespace std;
int n,m,k,s,t;
int mp[1010][1010];//a[i][j]表示(i,j)上的岛屿的标号,没有就是0
int x[1010],y[1010];
int vis[1010];//标记到达过的岛屿
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
void dfs(int x0,int y0)//拓展
{
vis[mp[x0][y0]]=1;
for(int i=0;i<4;i++)
{
int xx=x0+dx[i];
int yy=y0+dy[i];
if(xx<=0||xx>n||yy<0||yy>m||vis[mp[xx][yy]]||mp[xx][yy]==0)//不能走到没岛屿的地方或者重复走
continue;
dfs(xx,yy);
}
}
int main()
{
cin>>n>>m>>k>>s>>t;
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x[i],&y[i]);
mp[x[i]][y[i]]=i;
}
int T;
cin>>T;
int tot=0;
dfs(x[s],y[s]);
if(vis[t])
{
cout<<"0";
return 0;
}
while(T--)
{
int a,b,xx,yy;
scanf("%d%d",&a,&b);
if(b==1)
{
xx=x[a];
yy=y[a]+1;
}
if(b==2)
{
xx=x[a];
yy=y[a]-1;
}
if(b==3)
{
xx=x[a]-1;
yy=y[a];
}
if(b==4)
{
xx=x[a]+1;
yy=y[a];
}
if(mp[xx][yy]||xx<=0||xx>n||yy<=0||yy>m)//注意不能撞到岛屿
{
tot++;
continue;
}
mp[x[a]][y[a]]=0;
x[a]=xx;
y[a]=yy;
mp[x[a]][y[a]]=a;
if(vis[a])//移动了一个之前可经过的
dfs(x[a],y[a]);
else
{
for(int i=0;i<4;i++)
{
int tx=xx+dx[i];
int ty=yy+dy[i];
if(vis[mp[tx][ty]])
{
dfs(tx,ty);
}
}
}
tot++;
if(vis[t])
{
cout<<tot<<endl;
return 0;
}
}
cout<<"-1";
return 0;
} 


京公网安备 11010502036488号