题解 P5195 【[USACO05DEC]Knights of Ni 骑士】

· · 题解

先用$BFS$求出起点与终点到其他点的最短距离,然后在枚举每个沼泽,把每个沼泽到终点与起点的最短距离相加,最后打个擂台求最小的就是答案。 话不多说,上代码: ```cpp #include <iostream> #include <queue> #include <cstring> using namespace std; struct map{ int x,y; }; int dis1[1010][1010],dis2[1010][1010];//dis1表示从起点到其它点的最短路,dis2表示从终点到其它点的最短路 int a[1010][1010];//森林地图 int n,m,x1,y1,x2,y2; const int way[4][2]={{0,-1},{-1,0},{1,0},{0,1}}; void bfs(int x,int y) { memset(dis1,50,sizeof(dis1));//初始化 queue<map>q; q.push((map){x,y}); dis1[x][y]=0; while(!q.empty()) { map v=q.front(); q.pop(); for(int i=0; i<4; i++) { int nx=v.x+way[i][0],ny=v.y+way[i][1];//枚举下一个点 if(nx<1||nx>n||ny<1||ny>m) continue;//防止越界 if(a[nx][ny]==1) continue;//这个点一定要是可走的点 if(dis1[v.x][v.y]+1<dis1[nx][ny]) { dis1[nx][ny]=dis1[v.x][v.y]+1; q.push((map){nx,ny}); } } } } void bfs2(int x,int y)//同上 { memset(dis2,50,sizeof(dis2)); queue<map>q; q.push((map){x,y}); dis2[x][y]=0; while(!q.empty()) { map v=q.front(); q.pop(); for(int i=0; i<4; i++) { int nx=v.x+way[i][0],ny=v.y+way[i][1]; if(nx<1||nx>n||ny<1||ny>m) continue; if(a[nx][ny]==1) continue; if(dis2[v.x][v.y]+1<dis2[nx][ny]) { dis2[nx][ny]=dis2[v.x][v.y]+1; q.push((map){nx,ny}); } } } } int main() { cin>>m>>n; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { cin>>a[i][j]; if(a[i][j]==2) { x1=i,y1=j;//起点 } if(a[i][j]==3) { x2=i,y2=j;//终点 } } } bfs(x1,y1); bfs2(x2,y2); int ans=2000000000; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(a[i][j]==4) { ans=min(ans,dis1[i][j]+dis2[i][j]);//打擂台 } } } cout<<ans<<endl; return 0; } ```