leetcode 1970. 你能穿过矩阵的最后一天 困难

给你一个下标从 1 开始的二进制矩阵,其中 0 表示陆地,1 表示水域。同时给你 rowcol 分别表示矩阵中行和列的数目。

一开始在第 0 天,整个 矩阵都是 陆地 。但每一天都会有一块新陆地被 淹没变成水域。给你一个下标从 1 开始的二维数组 cells ,其中 cells[i] = [ri, ci] 表示在第 i 天,第 rici 列(下标都是从 1 开始)的陆地会变成 水域 (也就是 0 变成 1 )。

你想知道从矩阵最 上面 一行走到最 下面 一行,且只经过陆地格子的 最后一天 是哪一天。你可以从最上面一行的 任意 格子出发,到达最下面一行的 任意 格子。你只能沿着 四个 基本方向移动(也就是上下左右)。

请返回只经过陆地格子能从最 上面 一行走到最 下面 一行的 最后一天

示例 1:

复制代码
输入:row = 2, col = 2, cells = [[1,1],[2,1],[1,2],[2,2]]
输出:2
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 2 天。

示例 2:

复制代码
输入:row = 2, col = 2, cells = [[1,1],[1,2],[2,1],[2,2]]
输出:1
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 1 天。

示例 3:

复制代码
输入:row = 3, col = 3, cells = [[1,2],[2,1],[3,3],[2,2],[1,1],[1,3],[2,3],[3,2],[3,1]]
输出:3
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 3 天。

提示:

  • 2 <= row, col <= 2 * 10^4
  • 4 <= row * col <= 2 * 10^4
  • cells.length == row * col
  • 1 <= ri <= row
  • 1 <= ci <= col
  • cells 中的所有格子坐标都是 唯一 的。

分析:想象最上边有病毒,要感染到最下边。感染病毒的陆地标记为 2,变成水的位置标记为 1,其它没有感染病毒的陆地标记为 0.从最后一天开始,把倒序将所有水变回陆地。在变回陆地之前,先将第一行所有的陆地感染病毒,并进行 DFS,如果有某块陆地可以感染到最后一行,则直接返回最后一天作为答案。否则开始倒序遍历 cells,把水变成陆地。

这个过程中:如果陆地在第一行,则这块陆地被感染;如果陆地的上下左右都是水,或者都是未被感染的陆地,则它不被感染,否则这块陆地也被感染。对于被感染的陆地,进行一次 DFS,检查是否能到达最后一行,如果可以,则这天就是答案。

cpp 复制代码
int direction[4][2]={{1,0},{0,-1},{0,1},{-1,0}};

bool dfs(int **lands,int x,int y,int r,int c)
{
    if(x<=0||x>r||y<=0||y>c)return false;

    // printf("x=%d y=%d\n",x,y);

    if(lands[x][y]==0)
    {
        lands[x][y]=2;
        if(x==r)return true;
        for(int i=0;i<4;++i)
        {
            bool flag=dfs(lands,x+direction[i][0],y+direction[i][1],r,c);
            if(flag)return true;
        }
    }
    return false;
}

int latestDayToCross(int row, int col, int** cells, int cellsSize, int* cellsColSize) {
    int **lands=(int**)malloc(sizeof(int*)*(row+5));
    for(int i=0;i<row+5;++i)
        lands[i]=(int*)malloc(sizeof(int)*(col+5));
    for(int i=0;i<=row;++i)
        for(int j=0;j<=col;++j)
            lands[i][j]=0;

    for(int i=0;i<cellsSize;++i)
        lands[cells[i][0]][cells[i][1]]=1;
    
    for(int i=1;i<=col;++i)
    {
        if(lands[1][i]==0)
        {
            bool flag=dfs(lands,1,cells[1][i],row,col);
            if(flag==true)return cellsSize;
        }
    }

    for(int i=cellsSize-1;i>=0;--i)
    {
        int x=cells[i][0],y=cells[i][1];
        lands[x][y]=0;
        if(x==1||(lands[x-1][y]==2)||(x<row&&lands[x+1][y]==2)||(y>1&&lands[x][y-1]==2)||(y<col&&lands[x][y+1]==2))
        {
            bool flag=dfs(lands,cells[i][0],cells[i][1],row,col);
            if(flag==true)return i;
        }
    }

    for(int i=0;i<row;++i)
        free(lands[i]);
    free(lands);

    return 1;
}
相关推荐
We་ct1 天前
LeetCode 918. 环形子数组的最大和:两种解法详解
前端·数据结构·算法·leetcode·typescript·动态规划·取反
x_xbx1 天前
LeetCode:83. 删除排序链表中的重复元素
算法·leetcode·链表
xsyaaaan1 天前
leetcode-hot100-链表
leetcode·链表
逆境不可逃1 天前
LeetCode 热题 100 之 33. 搜索旋转排序数组 153. 寻找旋转排序数组中的最小值 4. 寻找两个正序数组的中位数
java·开发语言·数据结构·算法·leetcode·职场和发展
leaves falling1 天前
二分查找:迭代与递归实现全解析
数据结构·算法·leetcode
做怪小疯子1 天前
Leetcode刷题——深度优先搜索(DFS)
算法·leetcode·深度优先
想吃火锅10051 天前
【leetcode】105. 从前序与中序遍历序列构造二叉树
算法·leetcode·职场和发展
圣保罗的大教堂1 天前
leetcode 3567. 子矩阵的最小绝对差 中等
leetcode
老鼠只爱大米1 天前
LeetCode经典算法面试题 #215:数组中的第K个最大元素(快速选择、堆排序、计数排序等多种实现方案详解)
算法·leetcode·堆排序·快速选择·topk·数组中的第k个最大元素
逆境不可逃1 天前
LeetCode 热题 100 之 35. 搜索插入位置 74. 搜索二维矩阵 34. 在排序数组中查找元素的第一个和最后一个位置
数据结构·算法·leetcode