【Leetcode】1368. Minimum Cost to Make at Least One Valid Path in a Grid

题目地址:

https://leetcode.com/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid/

给定一个 m m m n n n列的二维矩阵,每个元素是 1 ∼ 4 1\sim 4 14之一, 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4分别代表右左下上四个方向。从 ( 0 , 0 ) (0,0) (0,0)这个位置出发,要走到 ( m − 1 , n − 1 ) (m-1,n-1) (m1,n1)这个位置,但是每一步只能按照格子里的方向走。允许改变若干个格子所代表的方向。问至少改变多少个格子可以使得从起点到终点是可达的。

这道题其实是个经典的双端队列BFS。将每个格子看成是图的顶点,相邻格子是有边相连接的。如果从顶点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2)的实际方向和矩阵在 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)的数字所表示的方向相同,则令这条边的边权为 0 0 0,否则令其边权为 1 1 1。原题相当于在问,在此图中,从起点到终点的最短路长度是多少。由于边权只有 0 0 0 1 1 1两种,所以可以用双端队列BFS来做。每次拓展的时候,如果是沿着边权 0 0 0的边走的,则插入队头,否则插入队尾。从队列里取元素的时候永远都从队头取。然后用堆优化的Dijkstra算法模板来写即可。具体详细思路参考https://blog.csdn.net/qq_46105170/article/details/114667171。代码如下:

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

public class Solution {
    public int minCost(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[] d = {1, 0, -1, 0, 1};
        // mapToD[i]表示d[i]所表示的方向在题目中的数字表示
        int[] mapToD = {3, 2, 4, 1};
        
        Deque<Integer> deque = new ArrayDeque<>();
        int[][] dist = new int[m][n];
        for (int[] row : dist) {
            Arrays.fill(row, Integer.MAX_VALUE);
        }
        boolean[][] visited = new boolean[m][n];
        
        deque.offerLast(0);
        dist[0][0] = 0;
        while (!deque.isEmpty()) {
            int cur = deque.pollFirst();
            if (visited[cur / n][cur % n]) {
                continue;
            }
            
            int x = cur / n, y = cur % n;
            // 终点第一次出队的时候,dist里存的就是最短路距离
            if (x == m - 1 && y == n - 1) {
                return dist[m - 1][n - 1];
            }
            
            visited[x][y] = true;
            for (int i = 0; i < 4; i++) {
                int nextX = x + d[i], nextY = y + d[i + 1];
                if (!(0 <= nextX && nextX < m && 0 <= nextY && nextY < n)) {
                    continue;
                }
                
                int e = grid[x][y] == mapToD[i] ? 0 : 1;
                if (!visited[nextX][nextY] && dist[nextX][nextY] > dist[x][y] + e) {
                    dist[nextX][nextY] = dist[x][y] + e;
                    if (e == 0) {
                        deque.offerFirst(nextX * n + nextY);
                    } else {
                        deque.offerLast(nextX * n + nextY);
                    }
                }
            }
        }
        
        return -1;
    }
}

时空复杂度 O ( m n ) O(mn) O(mn)

C++:

class Solution {
 public:
  struct Node {
    int x, y, dist;
  };

  int minCost(vector<vector<int>>& g) {
    int m = g.size(), n = g[0].size();
    deque<Node> dq;
    dq.push_back({0, 0, 0});
    bool vis[m][n];
    memset(vis, 0, sizeof vis);
    int dx[] = {0, 0, 1, -1};
    int dy[] = {1, -1, 0, 0};
    while (dq.size()) {
      auto t = dq.front();
      dq.pop_front();
      int x = t.x, y = t.y, dist = t.dist;
      if (x == m - 1 && y == n - 1) return dist;
      vis[x][y] = true;
      for (int i = 0; i < 4; i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (0 <= nx && nx < m && 0 <= ny && ny < n && !vis[nx][ny]) {
          if (g[x][y] == i + 1)
            dq.push_front({nx, ny, dist});
          else
            dq.push_back({nx, ny, dist + 1});
        }
      }
    }

    return -1;
  }
};

时空复杂度一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值