题目:
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例 1:
输入:
0 0 0
0 1 0
0 0 0
输出:
0 0 0
0 1 0
0 0 0
示例 2:
输入:
0 0 0
0 1 0
1 1 1
输出:
0 0 0
0 1 0
1 2 1
注意:
给定矩阵的元素个数不超过 10000。
给定矩阵中至少有一个元素是 0。
矩阵中的元素只在四个方向上相邻: 上、下、左、右。
链接:https://leetcode-cn.com/problems/01-matrix
分析
这里我主要是使用了DFS+剪枝,最好的方法应该是DP(不过我不太会,卑微)。
因为矩阵的元素不超过10000,所以可能是110000或者100001大小,如果直接开个数组(10000*10000)去存状态,会爆内存,所以这里我们使用map这一数据结构去存状态,判断该点有没有访问过。在主函数中,我们遍历矩阵中的每个值,如果其值不为0,且相邻不为0(第一个剪枝),则就需要修改,我们清空map数组,然后进行dfs操作,如果现在点的距离已经大于该点存的值,则就直接退出(第二个剪枝),如果到了0且距离比之前存的更小,则就更新,最后就得到了答案。
code:
struct Points
{
int x;
int y;
Points(int a, int b)
{
x = a;
y = b;
}
};
class Solution {
int row;
int col;
// 方向数组
int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
map<int, map<int, bool> > mp;
// 判断有没有超出范围
bool f(int i, int j)
{
if(i < 0 || j < 0 || i >= row || j >= col)
return false;
return true;
}
// 用来剪枝的函数
bool g(int x, int y, vector<vector<int>>& matrix)
{
for(int i = 0; i < 4; i++)
{
int xt = x + dirs[i][0];
int yt = y + dirs[i][1];
if(f(xt, yt) && matrix[xt][yt] == 0)
return false;
}
return true;
}
void dfs(vector<vector<int>>& matrix, int i, int j, int targetx, int targety)
{
int dis = abs(targetx-i) + abs(targety-j);
if(dis >= matrix[targetx][targety])
return ;
else if(matrix[i][j] == 0)
{
if(matrix[targetx][targety] > dis)
matrix[targetx][targety] = dis;
return ;
}
else
{
for(int k = 0; k < 4; k++)
{
int xt = i + dirs[k][0];
int yt = j + dirs[k][1];
if(f(xt, yt) && !mp[xt][yt])
{
mp[xt][yt] = true;
// cout << xt << '-' << yt << endl;
dfs(matrix, xt, yt, targetx, targety);
}
}
}
}
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
row = matrix.size();
if(row == 0)
return matrix;
col = matrix[0].size();
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
if(matrix[i][j] != 0 && g(i, j, matrix))
{
mp.erase(mp.begin(), mp.end());
matrix[i][j] = row+col;
mp[i][j] = 1;
dfs(matrix, i, j, i, j);
}
}
}
return matrix;
}
};