一道比较有思维难度的广搜题。
每一个时刻会有一个岛屿发生移动,求最快多长时间能到目标点,很容易想到广搜。
首先将起点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; }