题意:
题干:https://ac.nowcoder.com/acm/problem/235817 来源:牛客网
给定一片 n×mn\times mn×m 海域的洋流地图,其中每一个位置都有一个洋流。每次你可以向北、东北、东、东南、南、西南、西或者西北移动,并且不能离开这片海域。如果你当前坐标是 (x,y)(x,y)(x,y) ,按照上述方向移动后,你分别能达到坐标 (x−1,y)(x-1,y)(x−1,y) 、 (x−1,y+1)(x-1,y+1)(x−1,y+1) 、 (x,y+1)(x,y+1)(x,y+1) 、 (x+1,y+1)(x+1,y+1)(x+1,y+1) 、 (x+1,y)(x+1,y)(x+1,y) 、 (x+1,y−1)(x+1,y-1)(x+1,y−1) 、 (x,y−1)(x,y-1)(x,y−1) 和 (x−1,y−1)(x-1,y-1)(x−1,y−1) 。当你顺着洋流走时不消耗体力,否则你需要消耗1点体力。现给出 TTT 组询问,每组询问需要你回答从坐标 (x1,y1)(x_1,y_1)(x1,y1) 到 (x2,y2)(x_2,y_2)(x2,y2) 最少消耗多少体力。
思路:
一开始以为是bfs模板题,直接做可以通过样例但是会超时,考虑到搜索的优先度,应该是对于已经标记的点中选择最少的去遍历,于是选用deque这种双向开口的容器进行搜索,符合洋流方向的不必消耗,可以放在队头接着搜索,其他和普通的bfs相同。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std;
int a[1005][1005];
int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
int n,m,t;
int book[1005][1005];
int bfs(int sx,int sy,int ex,int ey){
memset(book,0x3f,sizeof(book));
book[sx][sy]=0;
deque<pair<int, int> > q;
q.push_front({sx,sy});
while(!q.empty()){
int x=q.front().first;
int y=q.front().second;
q.pop_front();
// cout<<x<<" "<<y<<endl;
if(x==ex&&y==ey){
return book[ex][ey];
}
for(int i=0;i<8;i++){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
int nnum=book[x][y];
if(i!=a[x][y]) nnum++;
if(nnum<book[tx][ty]){
book[tx][ty]=nnum;
if(nnum==book[x][y]) q.push_front({tx,ty});
else q.push_back({tx,ty});
}
}
}
}
return -1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
a[i][j]=c-'0';
}
}
cin>>t;
for(int i=1;i<=t;i++){
int sx,sy,ex,ey;
cin>>sx>>sy>>ex>>ey;
cout<<bfs(sx,sy,ex,ey)<<endl;
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<a[i][j]<<" ";
// }
// cout<<endl;
// }
return 0;
}
tips:好像用emplace_back 会比push_back 更高效。C++ emplace_back - 简书 (jianshu.com)
424

被折叠的 条评论
为什么被折叠?



