每日一题●1月5日 AcWing 2019.拖拉机

AcWing 2019. 拖拉机

干了一整天的活,农夫约翰完全忘记了他把拖拉机落在田地中央了。

他的奶牛非常调皮,决定对约翰来场恶作剧。

她们在田地的不同地方放了 N 捆干草,这样一来,约翰想要开走拖拉机就必须先移除一些干草捆。

拖拉机的位置以及 N 捆干草的位置都是二维平面上的整数坐标点。

拖拉机的初始位置上没有干草捆。

当约翰驾驶拖拉机时,他只能沿平行于坐标轴的方向(北,南,东和西)移动拖拉机,并且拖拉机必须每次移动整数距离。

例如,驾驶拖拉机先向北移动 2 单位长度,然后向东移动 3 单位长度。

拖拉机无法移动到干草捆占据的位置。

请帮助约翰确定他需要移除的干草捆的最小数量,以便他能够将拖拉机开到二维平面的原点。

输入格式

第一行包含三个整数:N 以及拖拉机的初始位置 (x,y)。

接下来 N 行,每行包含一个干草捆的位置坐标 (x,y)。

输出格式

输出约翰需要移除的干草捆的最小数量。

数据范围

1≤N≤50000,
1≤x,y≤1000

输入样例:
7 6 3
6 2
5 2
4 3
2 1
7 3
5 4
6 4

输出样例:

1
code:
#include<bits/stdc++.h>
#define x first
#define y second
typedef long long ll;
using namespace std;
typedef pair<int ,int >PII;
const int N=1010;
bool g[N][N],st[N][N];
int dist[N][N];
int bfs(int sx,int sy){
	deque<PII> q;//双端队列
	q.push_back({sx,sy});//插入队尾 
	memset(dist,0x3f,sizeof dist);//初始化距离无穷大 
	dist[sx][sy]=0;//起点到起点距离为0
	int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
	while(q.size()){
		auto t=q.front();//取队头
		q.pop_front();
		if(st[t.x][t.y]) continue;//如果已经搜索过了
		st[t.x][t.y] =true;//标记已搜索
		if(!t.x&&!t.y)break;//搜索到了原点
		for(int i=0;i<4;i++){//向四个方向搜索
			int x=t.x+dx[i],y=t.y+dy[i];
			if(x>=0&&x<N&&y>=0&&y<N){//如果超出了放障碍物的范围就不用再搜了
				int w=0;
				if(g[x][y]) w=1;//如果有障碍物 设权重是1
				if(dist[x][y]>dist[t.x][t.y]+w){//如果走当前点的障碍物数更少
					dist[x][y]=dist[t.x][t.y]+w;
					if(!w) q.push_front({x,y});//插入队头
					else q.push_back({x,y}); 	
				} 	
			} 		
		} 
	}
	return dist[0][0]; 
}
int main(){
	int n,sx,sy;
	scanf("%d%d%d",&n,&sx,&sy);
	while(n--){
		int x,y;
		scanf("%d%d",&x,&y);//障碍物
		g[x][y] = true;
	} 
	printf("%d\n",bfs(sx,sy));
	return 0;
}
}

bfs+双端队列,可以解决这种权值为0和1的最短路问题。
权值为0放队头,权值为1放队尾

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值