Algorithm 最小化矩阵中x和y之间的曼哈顿距离

Algorithm 最小化矩阵中x和y之间的曼哈顿距离,algorithm,matrix,data-structures,Algorithm,Matrix,Data Structures,我想解决一个关于曼哈顿距离和矩阵的问题 问题: 给定一个2D矩阵,其中每个单元格可能包含字符“0”或“x”或“y”。找到x和y之间的最小曼哈顿距离 x和y之间的曼哈顿距离为| x(x)-x(y)|+| y(x)-y(y)|。X&Y分别表示行数、列数。指矩阵中包含字符的单元格 例如: [ x, 0, 0, 0 ] [ 0, y, 0, y ] [ x, x, 0, 0 ] [ 0, y, 0, 0 ] 我们必须计算x和y之间的最小曼哈顿距离;在这种情况下,它是1(介于(3,2)和(4,2)之间)

我想解决一个关于曼哈顿距离和矩阵的问题

问题: 给定一个2D矩阵,其中每个单元格可能包含字符“0”或“x”或“y”。找到x和y之间的最小曼哈顿距离

x和y之间的曼哈顿距离为| x(x)-x(y)|+| y(x)-y(y)|。X&Y分别表示行数、列数。指矩阵中包含字符的单元格

例如:

[ x, 0, 0, 0 ]
[ 0, y, 0, y ]
[ x, x, 0, 0 ]
[ 0, y, 0, 0 ]
我们必须计算x和y之间的最小曼哈顿距离;在这种情况下,它是1(介于(3,2)和(4,2)之间)


一个蛮力方法相当于O((m*n)^2)次,如何将其优化到至少O(m*n)

这是一个经典的图论问题

首先请注意,曼哈顿距离只是网格上从一个单元格到另一个单元格的最短路径

然后将标有
x
的节点添加到队列中,直到您访问了某个
y
节点为止,到该节点的距离就是答案

复杂度:O(n*m)

示例代码(C++):

int n=4;
常数int inf=1234567890;
向量={“x000”、“0y0y”、“xx00”、“0y00”};
向量(n,向量(n,inf));
queueQ;

对于(inti=0;i,不使用图论

  • 将任何
    x_i
    的坐标放入集合
    x
  • 将任何
    y_j
    的坐标放入集合
    y
  • 在x和y idem的笛卡尔积上应用距离 考虑<代码> d(xi i,yjJ)< /> >所有<代码> ij>代码> <
  • 保持最低限度
如果
x\u s
的大小是
x
y\u s
的大小是
y
:在
O(x\u sy\u s)
中运行(假设您事先知道
x\u i
y\u j
。(O(mn)否则)

let{x,y}=`x000,0y0y,xx00,0y00`。替换(/,/g',)。拆分(“”)。减少((acc,v,id)=>{
设y=id%4;
设x=(id-y)/4
如果(v='x'| | v=='y'){
acc[v]。推力([x,y]);
}
返回acc;
},{x:[],y:[]})
设d=(a,b)=>Math.abs(a[1]-b[1])+Math.abs(a[0]-b[0]);

console.log('dist:',Math.min(…x.map(v=>Math.min(…y.map(w=>d(v,w)
对于矩阵的每个单元格,最小曼哈顿距离就是到左边最近的x和上面最近的y的y的距离,或者左边最近的x和上面最近的y的y的距离。
O(n
内存以跟踪每列中最近的x和y(与
O(n*m)
宽度优先搜索的最坏情况相比)

int n = 4;
const int inf = 1234567890;
vector<string>M = {"x000","0y0y","xx00","0y00"};
vector<vector<int>>D(n, vector<int>(n,inf));
queue<array<int,2>>Q;

for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
    if(M[i][j]=='x')
{
    Q.push({i,j});
    D[i][j]=0;
}

int res = inf;

while(!Q.empty())
{
    int row = Q.front()[0];
    int col = Q.front()[1];
    if(M[row][col]=='y')
    {
        res=D[row][col];
        break;
    }
    Q.pop();

    int dr[] = {-1,1,0,0};
    int dc[] = {0,0,-1,1};

    for(int k=0; k<4; k++)
    {
        int r = row + dr[k];
        int c = col + dc[k];
        if(min(r,c) >=0 && max(r,c) < n && D[r][c]==inf)
        {
            D[r][c]=D[row][col]+1;
            Q.push({r,c});
        }
    }
}

cout<<res;
def distance(M):
    rows = len(M)
    cols = len(M[0])
    above_x = cols * [-1]
    above_y = cols * [-1]
    res = float('inf')
    for row in range(rows):
        left_x = -1
        left_y = -1
        for col in range(cols):
            # track the nearest x and y to the left and above
            if M[row][col] == 'x':
                above_x[col] = row
                left_x = col
            if M[row][col] == 'y':
                above_y[col] = row
                left_y = col

            # the shortest distance is just the two distances added together
            if left_y > -1 and above_x[col] > -1:
                res = min(res, (col - left_y) + (row - above_x[col]))
            if left_x > -1 and above_y[col] > -1:
                res = min(res, (col - left_x) + (row - above_y[col]))
    return res