• 面试题 08.02. 迷路的机器人(C++)


    DP一遍过无剪枝 -- 解题思路:
    类似题:62不同路径
    在类似题中,用dp[i][j]表示到达(i, j)的方案数
    联想到 => 用dp[i][j]表示这条路能否走
    验证:用dp[i][j]表示解的状态(下标(i,j)是否在解的路径上)
    首先如果起点或者终点就是障碍,那么直接不可能有解的路径
    设定了状态,找状态转移方程:

    如果dp[i][j] == 1,即dp[i][j]本来就是障碍,那么直接走不通,无需考虑
    如果dp[i][j] == 0,就有如下考虑:
    设n = 行数, m = 列数
    1.当i == n - 1 && j == m - 1时,终点,直接过
    2.当i == n - 1时,它只能往右走,那么dp[i][j]的状态就取决于dp[i][j + 1],如果右边走不通,这个点也就不在解的路径上,这时就将这个点置1
    3.当j == m - 1时,它只能往下走,那么dp[i][j]的状态就取决于dp[i + 1][j],如果右边走不通,这个点也就不在解的路径上,这时就将这个点置1
    4.其他情况,机器人可以往右走或者往下走,那么dp[i][j]的状态就取决于dp[i][j + 1]或者dp[i + 1][j],如果右边和下边都走不通,那么(i, j)也就不在解的路径上,那么我们也可以将它看成障碍。如果左边或者右边有一个点走得通,那么(i, j)就在解的路径上。
    所以状态转移方程为:

    dp[i][j] == 1,直接忽略
    dp[i][j] == 0,分情况考虑:
    1.i == n - 1 && j == m - 1 , 忽略
    2.i == n - 1 : dp[i][j] = dp[i][j + 1] 只能往右走
    3.j == m - 1 : dp[i][j] = dp[i + 1][j] 只能往下走
    4.其他 : dp[i][j] = dp[i + 1][j] & dp[i][j + 1] 可以往下走也可以往右走
    这样遍历完,我们就可以判断dp[0][0]是否为1判定是否有解:

    无解,直接返回空数组
    有解,dfs寻找路径:
    寻找路径时,因为dp[i][j] == 0就代表这个点一定在其中一条路径上,而我们只需要求一条路径,所以我们我们只需判断往下走或者往右走即可。
    PS:这里说一下DP遍历时 i, j 从大到小还是从小到大的问题,这个取决于状态转移方程,如果当前状态取决于 i + 1,那么i 就是从大到小,对j也是如此。反之亦然。

    代码以及注释如下:


    class Solution {
    public:
    vector<vector<int>> res;
    void dfs(vector<vector<int>>& dp, int i, int j){
    int n = dp.size(), m = dp[0].size();
    res.push_back({i, j});
    if(i == n - 1 && j == m - 1) return ;
    //我们只要找到一条路径就行,所以只要一个条件通了就完成了,0的路径就是解
    if(i < n - 1 && dp[i + 1][j] == 0) dfs(dp, i + 1, j);
    else if(j < m - 1 && dp[i][j + 1] == 0) dfs(dp, i, j + 1);
    }
    vector<vector<int>> pathWithObstacles(vector<vector<int>>& obstacleGrid){
    int n = obstacleGrid.size(), m = obstacleGrid[0].size();
    if(obstacleGrid[0][0] == 1 || obstacleGrid[n - 1][m - 1] == 1) return {}; //起点或者终点为1,直接走不通
    vector<vector<int>> dp = obstacleGrid;
    for(int i = n - 1; i >= 0; i--){
    for(int j = m - 1; j >= 0; j--){ //状态转移方程
    if((i == n - 1 && j == m - 1) || dp[i][j] == 1) continue;
    if(i == n - 1) dp[i][j] = dp[i][j + 1];
    else if(j == m - 1) dp[i][j] = dp[i + 1][j];
    else dp[i][j] = dp[i + 1][j] & dp[i][j + 1];
    }
    }
    if(dp[0][0] == 1) return {}; //说明走不通,直接返回
    dfs(dp, 0, 0);
    return res;
    }
    };

    作者:spacex-1
    链接:https://leetcode-cn.com/problems/robot-in-a-grid-lcci/solution/c-dpyi-bian-guo-si-lu-zheng-li-by-spacex-cr1u/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    php增加自动刷新当前页面
    liunx环境下安装mysql5.7及以上版本
    mysql的主从级联复制的配置
    windowns常用命令
    liunx之使用(mount)挂载技术
    在burpsuite中为什么不能选中设置好的代理?
    c++中向任意目录下写文件
    Hbase——JavaAPI操作笔记
    每周总结(6)(补)
    每周总结(5)
  • 原文地址:https://www.cnblogs.com/kxzh/p/14145944.html
Copyright © 2020-2023  润新知