本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。
欢迎大家订阅我的专栏:算法题解:C++与Python实现!
附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总
【题目来源】
洛谷:P2873 [USACO07DEC] Mud Puddles S – 洛谷
【题目描述】
农夫约翰在早上
6
6
6 点准时离开家去挤奶贝茜。然而,前一天晚上下了大雨,田地里非常泥泞。约翰从坐标平面上的点
(
0
,
0
)
(0,0)
(0,0) 出发,前往位于
(
X
,
Y
)
(X,Y)
(X,Y) 的贝茜(
−
500
≤
X
≤
500
-500\\le X\\le 500
−500≤X≤500;
−
500
≤
Y
≤
500
-500\\le Y\\le 500
−500≤Y≤500)。他可以看到田地上所有
N
(
1
≤
N
≤
10
,
000
)
N(1\\le N\\le 10,000)
N(1≤N≤10,000) 个泥坑,位于点
(
A
i
,
B
i
)
(A_i,B_i)
(Ai,Bi)(
−
500
≤
A
i
≤
500
-500\\le A_i\\le 500
−500≤Ai≤500;
−
500
≤
B
i
≤
500
-500\\le B_i\\le 500
−500≤Bi≤500)。每个泥坑只占据它所在的点。
刚买了新靴子的农夫约翰绝对不想弄脏他的靴子,但他也想尽快到达贝茜。他已经迟到了,因为他不得不数清所有的泥坑。如果农夫约翰只能平行于坐标轴行走,并且只能在整数坐标点处转弯,那么他到达贝茜并保持靴子干净的最短距离是多少?总会有一条没有泥的路径可以让农夫约翰到达贝茜。
【输入】
- 第
1
1
1 行:三个用空格分隔的整数:X
,
Y
,
N
X,Y,N
X,Y,N。 - 第
2
2
2 行到第N
+
1
N+1
N+1 行:第i
+
1
i+1
i+1 行包含两个用空格分隔的整数:A
i
A_i
Ai 和B
i
B_i
Bi。
【输出】
- 第
1
1
1 行:农夫约翰到达贝茜而不踩到泥的最短距离。
【输入样例】
1 2 7
0 2
-1 3
3 1
1 1
4 2
-1 1
2 2
【输出样例】
11
【核心思想】
问题分析:给定起点
(
0
,
0
)
(0,0)
(0,0)、终点
(
X
,
Y
)
(X,Y)
(X,Y) 和
N
N
N 个泥坑坐标,FJ 只能沿坐标轴方向在整数点移动,不能踩泥坑。求到达终点的最短距离。这是一个BFS最短路/网格避障问题,关键在于将坐标偏移处理(避免负数下标),用BFS在无障碍网格上求最短路。
算法选择:
- BFS(广度优先搜索):四方向移动,边权均为
1
1
1,BFS天然适合求无权图最短路 - 坐标偏移:所有坐标加
500
500
500,将[
−
500
,
500
]
[-500, 500]
[−500,500] 映射到[
0
,
1000
]
[0, 1000]
[0,1000],避免负数数组下标 - 边界剪枝:根据泥坑和起终点的坐标范围,限制BFS搜索边界,避免无限扩展
关键步骤:
- 读取输入:
X
,
Y
,
N
X, Y, N
X,Y,N 和N
N
N 个泥坑坐标(
A
i
,
B
i
)
(A_i, B_i)
(Ai,Bi) - 坐标偏移与标记:所有坐标加
500
500
500,泥坑位置a
[
A
i
+
500
]
[
B
i
+
500
]
=
1
a[A_i+500][B_i+500] = 1
a[Ai+500][Bi+500]=1 - 确定搜索边界:
-
m
i
n
x
=
min
(
所有泥坑
x
,
500
)
minx = \\min(\\text{所有泥坑}x, 500)
minx=min(所有泥坑x,500),m
a
x
x
=
max
(
所有泥坑
x
,
500
)
maxx = \\max(\\text{所有泥坑}x, 500)
maxx=max(所有泥坑x,500) -
m
i
n
y
=
min
(
所有泥坑
y
,
500
)
miny = \\min(\\text{所有泥坑}y, 500)
miny=min(所有泥坑y,500),m
a
x
y
=
max
(
所有泥坑
y
,
500
)
maxy = \\max(\\text{所有泥坑}y, 500)
maxy=max(所有泥坑y,500) - 搜索范围扩展
1
1
1 格边界:[
m
i
n
x
−
1
,
m
a
x
x
+
1
]
×
[
m
i
n
y
−
1
,
m
a
x
y
+
1
]
[minx-1, maxx+1] \\times [miny-1, maxy+1]
[minx−1,maxx+1]×[miny−1,maxy+1]
-
- BFS过程:
- 起点
(
500
,
500
)
(500, 500)
(500,500) 入队,步数s
t
e
p
=
0
step = 0
step=0 - 取出队首,四方向扩展:
- 若越界:跳过
- 若到达终点
(
X
+
500
,
Y
+
500
)
(X+500, Y+500)
(X+500,Y+500):输出s
t
e
p
+
1
step + 1
step+1 并结束 - 若不是泥坑且未访问:标记访问,入队
- 起点
- 输出答案
时间/空间复杂度:
- 时间复杂度:
O
(
(
搜索范围宽度
)
×
(
搜索范围高度
)
)
O((\\text{搜索范围宽度}) \\times (\\text{搜索范围高度}))
O((搜索范围宽度)×(搜索范围高度)),最坏O
(
1002
×
1002
)
O(1002 \\times 1002)
O(1002×1002) - 空间复杂度:
O
(
1005
×
1005
)
O(1005 \\times 1005)
O(1005×1005),访问标记和泥坑标记数组
BFS网格最短路的核忈思想:
- 坐标偏移处理负数:通过统一加偏移量,将可能为负的坐标映射到非负数组下标
- 层序扩展保证最优:BFS按步数分层,首次到达终点时即为最短路径(曼哈顿距离意义下)
- 边界限制优化:根据输入数据的实际范围确定搜索边界,避免向无穷远处扩展
- 适用于"网格避障最短路径"类问题,核心是正确处理坐标和边界
【解题思路】

【算法标签】
#普及- #BFS-二维
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, sx, sy, minx=1e9, miny=1e9, maxx=–1e9, maxy=–1e9, dx[4]={–1,1,0,0}, dy[4]={0,0,–1,1}, tx, ty, tstep;
int a[1005][1005]={0}, vis[1005][1005]={0};
struct node {
int x, y, step, visit;
};
int main()
{
cin >> sx >> sy >> n; // 输入结束坐标及n
for (int i=1; i<=n; i++) { // 遍历n个泥塘坐标
int tmp1, tmp2;
cin >> tmp1 >> tmp2; // 输入坐标
minx = min(minx, tmp1+500); // 计算x坐标最小值
maxx = max(maxx, tmp1+500); // 计算x坐标最大值
miny = min(miny, tmp2+500); // 计算y坐标最小值
maxy = max(maxy, tmp2+500); // 计算y坐标最大值
a[tmp1+500][tmp2+500]=1; // 因为存在负数,x和y均加上500,对于泥塘的坐标,a数组置为1
}
minx = min(minx, 500); // 再与(0,0)(即(500,500))进行比较
maxx = max(maxx, 500);
miny = min(miny, 500);
maxy = max(maxy, 500);
queue<node> q; // 定义队列
node tp = {500, 500, 0}; // 队头数据
q.push(tp); // 压入队列
while (!q.empty()) { // bfs模板
tp = q.front();
q.pop();
for (int i=0; i<4; i++) { // 进行上下左右位置移动
tx = tp.x + dx[i];
ty = tp.y + dy[i];
tstep = tp.step+1; // 每移动一个格子,step加1
if (tx<minx–1||tx>maxx+1||ty<miny–1||ty>maxy+1) continue; // 当移动后的坐标越界时,继续循环
if (tx==sx+500 && ty==sy+500) { // 当遇到终点时,打印step,退出循环
cout << tstep << endl;
return 0;
}
if (a[tx][ty]==0 && vis[tx][ty]==0) { // 将要移动的坐标不是泥塘,且没有访问过
vis[tx][ty]=1; // 更新vis数组
node t = {tx, ty, tstep}; // 初始化t节点
q.push(t); // 将其压入队列中
}
}
}
return 0;
}
【运行结果】
1 2 7
0 2
-1 3
3 1
1 1
4 2
-1 1
2 2
11

![P11246 [GESP202409 六级] 小杨和整数拆分-171主机测评](https://www.171host.com/wp-content/uploads/2026/11/20261108100631-6af049a75855c-220x150.png)
![打卡信奥刷题(3678)用C++实现信奥题 P12274 [蓝桥杯 2024 国 Python B] 设计-171主机测评](https://www.171host.com/wp-content/uploads/2026/11/20261108053830-6af00ad6bdf8d-220x150.png)

