📌  相关文章
📜  找出从一个矩阵单元移动到另一个单元所需的最小移动次数

📅  最后修改于: 2022-05-13 01:57:53.930000             🧑  作者: Mango

找出从一个矩阵单元移动到另一个单元所需的最小移动次数

给定一个填充有 1 , 0 , 2 , 3 的 NXN 矩阵 (M)。找出从源移动到目的地(汇)所需的最少移动次数。仅遍历空白单元格。您可以向上、向下、向右和向左移动。
单元格1的值表示源。
单元格2的值表示目的地。
单元格3的值表示空白单元格。
单元格0的值表示空白墙。

注意:只有单一来源和单一目的地。从源到目的地(汇)的路径可能不止一条。矩阵中的每个移动我们认为是“1”

例子:

Input : M[3][3] = {{ 0 , 3 , 2 },
                   { 3 , 3 , 0 },
                   { 1 , 3 , 0 }};
Output : 4 

Input : M[4][4] = {{ 3 , 3 , 1 , 0 },
                   { 3 , 0 , 3 , 3 },
                   { 2 , 3 , 0 , 3 },
                   { 0 , 3 , 3 , 3 }};
Output : 4

提问:Adobe 面试
.

minimum_move

这个想法是使用一个级别图(广度优先遍历)。将每个单元格视为一个节点,任何两个相邻单元格之间的每个边界都是一条边。所以Node的总数是N*N。

  1. 1. 创建一个具有 N*N 节点(顶点)的空图。
  2. 2. 将所有节点推入一个图中。
  3. 3. 记下源点和汇点。
  4. 4. 现在应用级别图概念(我们使用 BFS 实现)。在其中我们从源顶点找到每个节点的级别。之后,我们返回 'Level[d]' (d 是目的地)。 (这是从源到接收器的最小移动)

下面是上述思想的实现。

C++
// C++ program to find the minimum numbers
// of moves needed to move from source to
// destination .
#include
using namespace std;
#define N 4
 
class Graph
{
    int V ;
    list < int > *adj;
public :
    Graph( int V )
    {
        this->V = V ;
        adj = new list[V];
    }
    void addEdge( int s , int d ) ;
    int BFS ( int s , int d) ;
};
 
// add edge to graph
void Graph :: addEdge ( int s , int d )
{
    adj[s].push_back(d);
    adj[d].push_back(s);
}
 
// Level  BFS function to find minimum path
// from source to sink
int Graph :: BFS(int s, int d)
{
    // Base case
    if (s == d)
        return 0;
 
    // make initial distance of all vertex -1
    // from source
    int *level = new int[V];
    for (int i = 0; i < V; i++)
        level[i] = -1  ;
 
    // Create a queue for BFS
    list queue;
 
    // Mark the source node level[s] = '0'
    level[s] = 0 ;
    queue.push_back(s);
 
    // it will be used to get all adjacent
    // vertices of a vertex
    list::iterator i;
 
    while (!queue.empty())
    {
        // Dequeue a vertex from queue
        s = queue.front();
        queue.pop_front();
 
        // Get all adjacent vertices of the
        // dequeued vertex s. If a adjacent has
        // not been visited ( level[i] < '0') ,
        // then update level[i] == parent_level[s] + 1
        // and enqueue it
        for (i = adj[s].begin(); i != adj[s].end(); ++i)
        {
            // Else, continue to do BFS
            if (level[*i] < 0 || level[*i] > level[s] + 1 )
            {
                level[*i] = level[s] + 1 ;
                queue.push_back(*i);
            }
        }
 
    }
 
    // return minimum moves from source to sink
    return level[d] ;
}
 
bool isSafe(int i, int j, int M[][N])
{
    if ((i < 0 || i >= N) ||
            (j < 0 || j >= N ) || M[i][j] == 0)
        return false;
    return true;
}
 
// Returns minimum numbers of  moves  from a source (a
// cell with value 1) to a destination (a cell with
// value 2)
int MinimumPath(int M[][N])
{
    int s , d ; // source and destination
    int V = N*N+2;
    Graph g(V);
 
    // create graph with n*n node
    // each cell consider as node
    int k = 1 ; // Number of current vertex
    for (int i =0 ; i < N ; i++)
    {
        for (int j = 0 ; j < N; j++)
        {
            if (M[i][j] != 0)
            {
                // connect all 4 adjacent cell to
                // current cell
                if ( isSafe ( i , j+1 , M ) )
                    g.addEdge ( k , k+1 );
                if ( isSafe ( i , j-1 , M ) )
                    g.addEdge ( k , k-1 );
                if (j< N-1 && isSafe ( i+1 , j , M ) )
                    g.addEdge ( k , k+N );
                if ( i > 0 && isSafe ( i-1 , j , M ) )
                    g.addEdge ( k , k-N );
            }
 
            // source index
            if( M[i][j] == 1 )
                s = k ;
 
            // destination index
            if (M[i][j] == 2)
                d = k;
            k++;
        }
    }
 
    // find minimum moves
    return g.BFS (s, d) ;
}
 
// driver program to check above function
int main()
{
    int M[N][N] = {{ 3 , 3 , 1 , 0 },
        { 3 , 0 , 3 , 3 },
        { 2 , 3 , 0 , 3 },
        { 0 , 3 , 3 , 3 }
    };
 
    cout << MinimumPath(M) << endl;
 
    return 0;
}


Python3
# Python3 program to find the minimum numbers
# of moves needed to move from source to
# destination .
 
class Graph:
    def __init__(self, V):
        self.V = V
        self.adj = [[] for i in range(V)]
 
    # add edge to graph
    def addEdge (self, s , d ):
        self.adj[s].append(d)
        self.adj[d].append(s)
     
    # Level BFS function to find minimum
    # path from source to sink
    def BFS(self, s, d):
         
        # Base case
        if (s == d):
            return 0
     
        # make initial distance of all
        # vertex -1 from source
        level = [-1] * self.V
     
        # Create a queue for BFS
        queue = []
     
        # Mark the source node level[s] = '0'
        level[s] = 0
        queue.append(s)
     
        # it will be used to get all adjacent
        # vertices of a vertex
     
        while (len(queue) != 0):
             
            # Dequeue a vertex from queue
            s = queue.pop()
     
            # Get all adjacent vertices of the
            # dequeued vertex s. If a adjacent has
            # not been visited ( level[i] < '0') ,
            # then update level[i] == parent_level[s] + 1
            # and enqueue it
            i = 0
            while i < len(self.adj[s]):
                 
                # Else, continue to do BFS
                if (level[self.adj[s][i]] < 0 or
                    level[self.adj[s][i]] > level[s] + 1 ):
                    level[self.adj[s][i]] = level[s] + 1
                    queue.append(self.adj[s][i])
                i += 1
     
        # return minimum moves from source
        # to sink
        return level[d]
 
def isSafe(i, j, M):
    global N
    if ((i < 0 or i >= N) or
        (j < 0 or j >= N ) or M[i][j] == 0):
        return False
    return True
 
# Returns minimum numbers of moves from a
# source (a cell with value 1) to a destination
# (a cell with value 2)
def MinimumPath(M):
    global N
    s , d = None, None # source and destination
    V = N * N + 2
    g = Graph(V)
 
    # create graph with n*n node
    # each cell consider as node
    k = 1 # Number of current vertex
    for i in range(N):
        for j in range(N):
            if (M[i][j] != 0):
                 
                # connect all 4 adjacent cell to
                # current cell
                if (isSafe (i , j + 1 , M)):
                    g.addEdge (k , k + 1)
                if (isSafe (i , j - 1 , M)):
                    g.addEdge (k , k - 1)
                if (j < N - 1 and isSafe (i + 1 , j , M)):
                    g.addEdge (k , k + N)
                if (i > 0 and isSafe (i - 1 , j , M)):
                    g.addEdge (k , k - N)
 
            # source index
            if(M[i][j] == 1):
                s = k
 
            # destination index
            if (M[i][j] == 2):
                d = k
            k += 1
 
    # find minimum moves
    return g.BFS (s, d)
 
# Driver Code
N = 4
M = [[3 , 3 , 1 , 0 ], [3 , 0 , 3 , 3 ],
     [2 , 3 , 0 , 3 ], [0 , 3 , 3 , 3]]
 
print(MinimumPath(M))
 
# This code is contributed by PranchalK


C++
// C++ program for the above approach
#include 
#define N 4
 
// To be used in DFS while comparing the
// minimum element
#define MAX (INT_MAX - 1)
using namespace std;
 
// Graph with the adjacency
// list representationo
class Graph {
private:
    int V;
    vector* adj;
 
public:
    Graph(int V)
        : V{ V }
    {
         
        // Initializing the
        // adjacency list
        adj = new vector[V];
    }
   
    // Clearing the memory after
    // its use (best practice)
    ~Graph()
    {
        delete[] adj;
    }
 
    // Adding the element to the
    // adjacency list matrix
    // representation
    void add_edges(int u, int v)
    {
      adj[u].push_back(v);
    }
 
    // performing the DFS for the minimum moves
    int DFS(int s, int d, unordered_set& visited)
    {
         
        // Base condition for the recursion
        if (s == d)
            return 0;
       
        // Initializing the result
        int res{ MAX };
        visited.insert(s);
        for (int item : adj[s])
            if (visited.find(item) ==
                         visited.end())
               
                // comparing the res with
                // the result of DFS
                // to get the minimum moves
                res = min(res, 1 + DFS(item, d, visited));
        return res;
    }
};
 
// ruling out the cases where the element
// to be inserted is outside the matrix
bool is_safe(int arr[][4], int i, int j)
{
    if ((i < 0 || i >= N) || (j < 0 || j >= N)
        || arr[i][j] == 0)
        return false;
    return true;
}
 
int min_moves(int arr[][N])
{
    int s{ -1 }, d{ -1 }, V{ N * N };
   
    /* k be the variable which represents the
       positions( 0 - N*N ) inside the graph.
    */
   
     // k moves from top-left to bottom-right
    int k{ 0 };
    Graph g{ V };
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++) {
           
            // Adding the edge
            if (arr[i][j] != 0) {
                if (is_safe(arr, i, j + 1))
                    g.add_edges(k, k + 1); // left
                if (is_safe(arr, i, j - 1))
                    g.add_edges(k, k - 1); // right
                if (is_safe(arr, i + 1, j))
                    g.add_edges(k, k + N); // bottom
                if (is_safe(arr, i - 1, j))
                    g.add_edges(k, k - N); // top
            }
           
            // Source from which DFS to be
            // performed
            if (arr[i][j] == 1)
                s = k;
           
            // Destination
            else if (arr[i][j] == 2)
                d = k;
           
            // Moving k from top-left
            // to bottom-right
            k++;
        }
    }
    unordered_set visited;
   
    // DFS performed from
    // source to destination
    return g.DFS(s, d, visited);
}
 
int32_t main()
{
    int arr[][N] = { { 3, 3, 1, 0 },
                     { 3, 0, 3, 3 },
                     { 2, 3, 0, 3 },
                     { 0, 3, 3, 3 } };
   
    // if(min_moves(arr) == MAX) there
    // doesn't exist a path
    // from source to destination
    cout << min_moves(arr) << endl;
    return 0;
   
    // the DFS approach and code
    // is contributed by Lisho
    // Thomas
}


Python3
# Python3 program for the above approach
 
# To be used in DFS while comparing the
# minimum element
# define MAX (I4T_MAX - 1)
visited = {}
adj = [[] for i in range(16)]
 
# Performing the DFS for the minimum moves
def add_edges(u, v):
     
    global adj
    adj[u].append(v)
 
def DFS(s, d):
     
    global visited
 
    # Base condition for the recursion
    if (s == d):
        return 0
 
    # Initializing the result
    res = 10**9
    visited[s] = 1
     
    for item in adj[s]:
        if (item not in visited):
             
            # Comparing the res with
            # the result of DFS
            # to get the minimum moves
            res = min(res, 1 + DFS(item, d))
 
    return res
 
# Ruling out the cases where the element
# to be inserted is outside the matrix
def is_safe(arr, i, j):
     
    if ((i < 0 or i >= 4) or
        (j < 0 or j >= 4) or arr[i][j] == 0):
        return False
         
    return True
 
def min_moves(arr):
 
    s, d, V = -1,-1, 16
    # k be the variable which represents the
    # positions( 0 - 4*4 ) inside the graph.
     
    # k moves from top-left to bottom-right
    k = 0
    for i in range(4):
        for j in range(4):
             
            # Adding the edge
            if (arr[i][j] != 0):
                if (is_safe(arr, i, j + 1)):
                    add_edges(k, k + 1) # left
                if (is_safe(arr, i, j - 1)):
                    add_edges(k, k - 1) # right
                if (is_safe(arr, i + 1, j)):
                    add_edges(k, k + 4) # bottom
                if (is_safe(arr, i - 1, j)):
                    add_edges(k, k - 4) # top
 
            # Source from which DFS to be
            # performed
            if (arr[i][j] == 1):
                s = k
                 
            # Destination
            elif (arr[i][j] == 2):
                d = k
                 
            # Moving k from top-left
            # to bottom-right
            k += 1
 
    # DFS performed from
    # source to destination
    return DFS(s, d)
 
# Driver code
if __name__ == '__main__':
     
    arr = [ [ 3, 3, 1, 0 ],
            [ 3, 0, 3, 3 ],
            [ 2, 3, 0, 3 ],
            [ 0, 3, 3, 3 ] ]
 
    # If(min_moves(arr) == MAX) there
    # doesn't exist a path
    # from source to destination
    print(min_moves(arr))
 
# This code is contributed by mohit kumar 29


输出:

4

另一种方法:(DFS实现的问题)

同样可以使用DFS来实现,其中比较源的完整路径以获得到目的地的最小移动。

方法

  1. 遍历输入矩阵中的每个元素并从该矩阵创建一个图形
    1. 创建一个具有 N*N 个顶点的图。
    2. 将第k个顶点的边添加到k+1 / k-1 (如果边在矩阵中的左侧或右侧元素)或kk+N/ kN (如果边到矩阵中的顶部或底部元素矩阵)。
    3. 始终检查元素是否存在于矩阵中且元素 != 0。
    4. if(element == 1) 映射源 if (element == 2) 映射目标。
  2. 对形成的图执行 DFS,从源到目标。
    1. 基本条件:如果 source==destination 返回 0 作为最小移动次数。
    2. 最小移动将是最小值(对未访问的相邻顶点执行 DFS 的结果)。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
#define N 4
 
// To be used in DFS while comparing the
// minimum element
#define MAX (INT_MAX - 1)
using namespace std;
 
// Graph with the adjacency
// list representationo
class Graph {
private:
    int V;
    vector* adj;
 
public:
    Graph(int V)
        : V{ V }
    {
         
        // Initializing the
        // adjacency list
        adj = new vector[V];
    }
   
    // Clearing the memory after
    // its use (best practice)
    ~Graph()
    {
        delete[] adj;
    }
 
    // Adding the element to the
    // adjacency list matrix
    // representation
    void add_edges(int u, int v)
    {
      adj[u].push_back(v);
    }
 
    // performing the DFS for the minimum moves
    int DFS(int s, int d, unordered_set& visited)
    {
         
        // Base condition for the recursion
        if (s == d)
            return 0;
       
        // Initializing the result
        int res{ MAX };
        visited.insert(s);
        for (int item : adj[s])
            if (visited.find(item) ==
                         visited.end())
               
                // comparing the res with
                // the result of DFS
                // to get the minimum moves
                res = min(res, 1 + DFS(item, d, visited));
        return res;
    }
};
 
// ruling out the cases where the element
// to be inserted is outside the matrix
bool is_safe(int arr[][4], int i, int j)
{
    if ((i < 0 || i >= N) || (j < 0 || j >= N)
        || arr[i][j] == 0)
        return false;
    return true;
}
 
int min_moves(int arr[][N])
{
    int s{ -1 }, d{ -1 }, V{ N * N };
   
    /* k be the variable which represents the
       positions( 0 - N*N ) inside the graph.
    */
   
     // k moves from top-left to bottom-right
    int k{ 0 };
    Graph g{ V };
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++) {
           
            // Adding the edge
            if (arr[i][j] != 0) {
                if (is_safe(arr, i, j + 1))
                    g.add_edges(k, k + 1); // left
                if (is_safe(arr, i, j - 1))
                    g.add_edges(k, k - 1); // right
                if (is_safe(arr, i + 1, j))
                    g.add_edges(k, k + N); // bottom
                if (is_safe(arr, i - 1, j))
                    g.add_edges(k, k - N); // top
            }
           
            // Source from which DFS to be
            // performed
            if (arr[i][j] == 1)
                s = k;
           
            // Destination
            else if (arr[i][j] == 2)
                d = k;
           
            // Moving k from top-left
            // to bottom-right
            k++;
        }
    }
    unordered_set visited;
   
    // DFS performed from
    // source to destination
    return g.DFS(s, d, visited);
}
 
int32_t main()
{
    int arr[][N] = { { 3, 3, 1, 0 },
                     { 3, 0, 3, 3 },
                     { 2, 3, 0, 3 },
                     { 0, 3, 3, 3 } };
   
    // if(min_moves(arr) == MAX) there
    // doesn't exist a path
    // from source to destination
    cout << min_moves(arr) << endl;
    return 0;
   
    // the DFS approach and code
    // is contributed by Lisho
    // Thomas
}

Python3

# Python3 program for the above approach
 
# To be used in DFS while comparing the
# minimum element
# define MAX (I4T_MAX - 1)
visited = {}
adj = [[] for i in range(16)]
 
# Performing the DFS for the minimum moves
def add_edges(u, v):
     
    global adj
    adj[u].append(v)
 
def DFS(s, d):
     
    global visited
 
    # Base condition for the recursion
    if (s == d):
        return 0
 
    # Initializing the result
    res = 10**9
    visited[s] = 1
     
    for item in adj[s]:
        if (item not in visited):
             
            # Comparing the res with
            # the result of DFS
            # to get the minimum moves
            res = min(res, 1 + DFS(item, d))
 
    return res
 
# Ruling out the cases where the element
# to be inserted is outside the matrix
def is_safe(arr, i, j):
     
    if ((i < 0 or i >= 4) or
        (j < 0 or j >= 4) or arr[i][j] == 0):
        return False
         
    return True
 
def min_moves(arr):
 
    s, d, V = -1,-1, 16
    # k be the variable which represents the
    # positions( 0 - 4*4 ) inside the graph.
     
    # k moves from top-left to bottom-right
    k = 0
    for i in range(4):
        for j in range(4):
             
            # Adding the edge
            if (arr[i][j] != 0):
                if (is_safe(arr, i, j + 1)):
                    add_edges(k, k + 1) # left
                if (is_safe(arr, i, j - 1)):
                    add_edges(k, k - 1) # right
                if (is_safe(arr, i + 1, j)):
                    add_edges(k, k + 4) # bottom
                if (is_safe(arr, i - 1, j)):
                    add_edges(k, k - 4) # top
 
            # Source from which DFS to be
            # performed
            if (arr[i][j] == 1):
                s = k
                 
            # Destination
            elif (arr[i][j] == 2):
                d = k
                 
            # Moving k from top-left
            # to bottom-right
            k += 1
 
    # DFS performed from
    # source to destination
    return DFS(s, d)
 
# Driver code
if __name__ == '__main__':
     
    arr = [ [ 3, 3, 1, 0 ],
            [ 3, 0, 3, 3 ],
            [ 2, 3, 0, 3 ],
            [ 0, 3, 3, 3 ] ]
 
    # If(min_moves(arr) == MAX) there
    # doesn't exist a path
    # from source to destination
    print(min_moves(arr))
 
# This code is contributed by mohit kumar 29
输出
4