给定一个 N ∗ M N∗M的 01 01矩阵 A A。其中, A [ i ] [ j ] A[i][j] 与 A [ k ] [ l ] A[k][l] 之间的曼哈顿距离定义为 d i s ( A [ i ] [ j ] , A [ k ] [ l ] ) = ∣ i − k ∣ + ∣ j − l ∣ dis(A[i][j],A[k][l])=∣i−k∣+∣j−l∣ 示例: 示例 1: 输入: 3 4 0001 0011 0110 输出: 3 2 1 0 2 1 0 0 1 0 0 1 用c++解决
时间: 2025-04-28 14:19:07 浏览: 52
<think>好的,我现在需要帮助用户解决他们在C++中计算01矩阵每个元素到最近1的曼哈顿距离的问题。首先,我需要理解用户的需求。他们提到了01矩阵,也就是由0和1组成的矩阵,要求计算每个元素到最近的1的曼哈顿距离。曼哈顿距离的计算方式是两点在网格上的绝对轴距总和,比如点(x1,y1)和(x2,y2)的距离是|x1-x2| + |y1-y2|。
接下来,我需要考虑如何高效地解决这个问题。用户提供的引用中有关于曼哈顿距离的C++实现,比如菱形图案的生成,但那个例子是固定中心点的,而这里需要动态找到最近的1。另外,用户之前的问题和回答涉及快速排序、类与对象、数据结构等,但当前问题更偏向图算法或动态规划。
首先,我应该想到可能的解决方案。常见的方法有两种:暴力法和多源BFS。暴力法对于每个0元素,遍历整个矩阵找到最近的1,但这样的时间复杂度是O((mn)^2),对于大矩阵来说效率很低。多源BFS则更高效,时间复杂度为O(mn),适合处理大规模数据。用户提供的引用中没有提到BFS,但根据我的知识,多源BFS是解决这类问题的标准方法。
接下来,我需要详细设计多源BFS的实现步骤。首先,初始化一个距离矩阵,所有1的位置距离为0,0的位置设为无穷大。然后将所有1的位置加入队列。接着,进行BFS,每次从队列中取出一个位置,检查其四个方向(上下左右),如果相邻的位置未被访问过且可以更新更小的距离,则更新并将该位置加入队列。这样,队列会按照距离递增的顺序处理每个节点,确保第一次访问时就是最短距离。
然后,我需要考虑C++的具体实现。使用队列结构,比如STL的queue,存储坐标。矩阵可以用二维数组或vector<vector<int>>表示。注意边界条件的处理,比如矩阵的行列范围。初始化时,遍历整个矩阵,找到所有1的位置,并将其加入队列,同时设置距离为0。对于0的位置,初始距离可以设置为一个很大的值,比如INT_MAX。
还需要考虑可能的错误和异常情况,例如空矩阵,或者矩阵中没有1的情况。在这些情况下,可能需要返回特定的结果或错误信息。但根据题目描述,假设矩阵是有效的,并且至少有一个1存在。
然后,测试代码的正确性。例如,给定一个示例矩阵,比如:
0 0 0
0 1 0
0 0 0
处理后应得到:
2 1 2
1 0 1
2 1 2
另一个测试用例可能包含多个1,确保算法能正确处理多个源头的情况。
用户提供的引用中,引用[2]提到了曼哈顿距离的Python实现,但这里是C++,需要转换。同时,引用[3]中的点云处理可能与当前问题关联不大,但可能涉及空间搜索算法,不过暂时可以忽略。
在代码编写时,要注意效率和内存使用。多源BFS的时间复杂度是线性的,空间复杂度也是O(mn),这对于大多数情况是可行的。此外,使用STL的队列和向量结构可以简化代码。
最后,总结实现步骤,并准备代码示例,同时解释关键点,比如BFS的应用、初始化和方向处理。确保代码有注释,便于用户理解。可能还需要比较不同方法的优缺点,说明为什么选择多源BFS。</think>根据您的问题需求,我将为您提供基于多源BFS的最优解法和分层递进式实现方案。以下是详细的实现步骤和代码分析:
---
### 一、问题理解与算法选择
**目标**:给定$m×n$的01矩阵,计算每个元素到最近1的曼哈顿距离
**关键点**:
1. **曼哈顿距离**:$distance = |x1-x2| + |y1-y2|$[^1]
2. **多源BFS优势**:时间复杂度$O(mn)$,空间复杂度$O(mn)$,优于暴力法的$O(m^2n^2)$[^2]
---
### 二、分层实现方案
#### 基础版(标准BFS实现)
```cpp
#include <vector>
#include <queue>
using namespace std;
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
queue<pair<int, int>> q;
// 初始化距离矩阵
vector<vector<int>> dist(m, vector<int>(n, -1));
for(int i=0; i<m; ++i) {
for(int j=0; j<n; ++j) {
if(mat[i][j] == 1) {
dist[i][j] = 0;
q.push({i, j}); // 多源起点入队
}
}
}
// 四方向向量
vector<pair<int, int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
while(!q.empty()) {
auto [x, y] = q.front();
q.pop();
for(auto [dx, dy] : dirs) {
int nx = x + dx, ny = y + dy;
if(nx>=0 && nx<m && ny>=0 && ny<n && dist[nx][ny]==-1) {
dist[nx][ny] = dist[x][y] + 1;
q.push({nx, ny});
}
}
}
return dist;
}
```
#### 优化版(空间压缩)
```cpp
vector<vector<int>> updateMatrix_optimized(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
queue<pair<int, int>> q;
// 复用输入矩阵存储距离(标记-1为未访问)
for(int i=0; i<m; ++i) {
for(int j=0; j<n; ++j) {
if(mat[i][j] == 1) {
mat[i][j] = 0; // 1的位置距离为0
q.push({i, j});
} else {
mat[i][j] = -1; // 标记未访问的0
}
}
}
vector<pair<int, int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
while(!q.empty()) {
auto [x, y] = q.front();
q.pop();
for(auto [dx, dy] : dirs) {
int nx = x + dx, ny = y + dy;
if(nx>=0 && nx<m && ny>=0 && ny<n && mat[nx][ny]==-1) {
mat[nx][ny] = mat[x][y] + 1;
q.push({nx, ny});
}
}
}
return mat;
}
```
---
### 三、算法解析
**核心逻辑**:
1. **多源初始化**:所有1的位置作为起点同时入队(距离0)
2. **层级扩散**:BFS天然保证首次访问时的距离最小性
3. **四方向探测**:使用方向向量简化代码
**复杂度对比**:
| 方法 | 时间复杂度 | 空间复杂度 |
|------------|------------|------------|
| 暴力法 | O(m²n²) | O(1) |
| 多源BFS | O(mn) | O(mn) |
| 优化版BFS | O(mn) | O(1) |
---
### 四、测试用例
```cpp
int main() {
// 测试用例
vector<vector<int>> mat = {
{0,0,0},
{0,1,0},
{0,0,0}
};
auto res = updateMatrix(mat);
// 输出结果应为:
// 2 1 2
// 1 0 1
// 2 1 2
for(auto& row : res) {
for(int val : row) cout << val << " ";
cout << endl;
}
return 0;
}
```
---
### 五、扩展应用
1. **图像处理**:计算像素到最近边缘的距离
2. **路径规划**:多目标点最短路径计算
3. **游戏开发**:势力范围扩散模拟
阅读全文
相关推荐



















