题目大意
小b现在玩一个极其无聊的游戏,它控制角色从基地出发,一路狂奔夺走了对方的水晶,可是正准备回城时,发现地图上已经生成了 n n n 个怪。
现在假设地图是二维平面,所有的怪和角色都认为是在这个二维平面的点上。请你帮小b计算一下,从现在角色的位置开始,至少要消灭几个怪才能回到基地(坐标原点)。
注意:小b控制的角色只能沿平行于坐标轴的方向移动(东、西、南、北),而且每次必须移动整数距离。
数据范围
1 ≤ n ≤ 50000 1≤n≤50000 1≤n≤50000
1 ≤ x , y ≤ 1000 1≤x,y≤1000 1≤x,y≤1000
输入格式
第一行包含三个整数: n n n 以及角色的初始位置 ( x , y ) (x,y) (x,y) 。
接下来 n n n 行,每行包含一个怪的位置坐标 ( x , y ) (x,y) (x,y)。
输出格式
一个数,表示最少要消灭的怪的个数。
输入样例
cpp
7 6 3
6 2
5 2
4 3
2 1
7 3
5 4
6 4
输出样例
cpp
1
基本思路
知道起点和终点,每次扩展一步,题目具有 b f s bfs bfs 的特征。
但是单纯 b f s bfs bfs 它只会管几层,而不会处理路过怪物数量。但题目要求最少经过怪物,所以绕路是十分必要的,而普通 b f s bfs bfs 中可能会让有怪物的点优先扩展,而违背了这个原则。
所以我们要介绍一个新东西,双端队列 d e q u e deque deque。顾名思义,就是队首队尾都可以进出元素。所以我们可以让无怪物的点从队头进,有怪物的点从队尾进,取的时候仍是从队头取。这样就可以尽可能绕开怪物,而不会让不得不消灭的怪物被排除。
核心代码
cpp
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e3+10;
struct node{
int x,y,cnt;
};
int n,sx,sy,w[4][2]={{0,1},{1,0},{0,-1},{-1,0}},ans=0x3f3f3f3f;
bool v[N][N],a[N][N];
deque<node>q;
inline int bfs(){
q.push_back({sx,sy,0});
v[sx][sy]=true;
while(!q.empty()){
node u=q.front();
q.pop_front();
if(u.x==0&&u.y==0)
return u.cnt;//到达终点
for(int i=0;i<4;i++){
int xx=u.x+w[i][0],yy=u.y+w[i][1];
if(xx<0||xx>=N||yy<0||yy>=N) continue;
if(v[xx][yy]==true) continue;
if(a[xx][yy]==true)
q.push_back({xx,yy,u.cnt+1});
else
q.push_front({xx,yy,u.cnt});
v[xx][yy]=true;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>sx>>sy;
for(int i=1,x,y;i<=n;i++){
cin>>x>>y;
a[x][y]=true;
}
cout<<bfs();
return 0;
}