题目
干了一整天的活,农夫约翰完全忘记了他把拖拉机落在田地中央了。
他的奶牛非常调皮,决定对约翰来场恶作剧。
她们在田地的不同地方放了 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
思路解析
读题 → 抽象题型为矩阵 → 转为常见模型——最短路径
此题用Dijkstra结合双端队列即可求解。
①任何时刻双端队列中所有点到原点的距离最多只有两端,且这两段只差1.
采用数学归纳法证明:
②题意可知:可走地图大小不止1000*1000
,也可在其外围走,因为在设计算法时可指定其走的面积为1001*1001
。
实现方法:
- 设置矩阵范围为
1002*1002
(1001*1001原则上也可以,但是由于计算问题,适当调大数字),即可满足矩阵上侧和右侧部分最外围一圈无障碍。- 矩阵遍历从
0
开始(其干草堆放置是从1
开始的),即可满足矩阵下侧和左侧部分最外围一圈无障碍。
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<deque> //双端队列的头文件
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 1002;//定义矩阵边长
bool g[N][N]; //记录位置上是否有障碍物(有:true 无:flase)
bool st[N][N]; //判端是否走过此处(走过:true 无:false)
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;
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 = g[x][y]==1 ?1:0;//如果是障碍物,权值置为1 ,否则置为0
//int w = 0;
//if (g[x][y]) w = 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;//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;
}
希望可以帮到你,欢迎点赞评论~