LeetCode 1824. 最少侧跳次数(C++)*

文章介绍了如何使用动态规划解决一个关于青蛙在3跑道道路上避开障碍并寻找最小侧跳次数的问题。给定一个障碍物数组,动态规划的状态转移方程用于计算到达每个点每条跑道所需的最少侧跳次数。最后返回到达终点的最小侧跳数。

思路:
首先动态规划的思路,三条道路,要求到三条跑道的最后一个点中的最短侧跳数;
设 d[i][j] 表示青蛙到达i号点的j号跑道时所需要的最少侧跳次数
如果说j号跑道obstacles[i]-1等于j,代表i号j跑道上有石头,不可能到该点所以距离无穷;
转移方程:
分为两类情况:本来就是这条道然and从另一条到侧跳到该道该点
1. d[i][j]=d[i-1][j] if j!=bostacles[i]-1; i处该跑道位置没有石头,该情况是本来就在j跑道的
2. d[i][j]=inf if j==bostacles[i]-1; i处该跑道位置有石头,那就不可能到这个点
3. d[i][j]=min(d[i][j],mid(d[i][0],d[i,2],d[i][1])+1);从另外的跑道侧跳过来的情况,且没有石头
原题链接:https://leetcode.cn/problems/minimum-sideway-jumps/

1.题目如下:

给你一个长度为 n 的 3 跑道道路 ,它总共包含 n + 1 个 点 ,编号为 0 到 n 。一只青蛙从 0 号点第二条跑道 出发 ,它想要跳到点 n 处。然而道路上可能有一些障碍。

给你一个长度为 n + 1 的数组 obstacles ,其中 obstacles[i] (取值范围从 0 到 3)表示在点 i 处的 obstacles[i] 跑道上有一个障碍。如果 obstacles[i] == 0 ,那么点 i 处没有障碍。任何一个点的三条跑道中 最多有一个 障碍。

比方说,如果 obstacles[2] == 1 ,那么说明在点 2 处跑道 1 有障碍。
这只青蛙从点 i 跳到点 i + 1 且跑道不变的前提是点 i + 1 的同一跑道上没有障碍。为了躲避障碍,这只青蛙也可以在 同一个 点处 侧跳 到 另外一条 跑道(这两条跑道可以不相邻),但前提是跳过去的跑道该点处没有障碍。

比方说,这只青蛙可以从点 3 处的跑道 3 跳到点 3 处的跑道 1 。
这只青蛙从点 0 处跑道 2 出发,并想到达点 n 处的 任一跑道 ,请你返回 最少侧跳次数 。

注意:点 0 处和点 n 处的任一跑道都不会有障碍。

示例 1:

输入:obstacles = [0,1,2,3,0]
输出:2 

解释:最优方案如上图箭头所示。总共有 2 次侧跳(红色箭头)。 注意,这只青蛙只有当侧跳时才可以跳过障碍(如上图点 2 处所示)。

示例 2:

输入:obstacles = [0,1,1,3,3,0]
输出:0

解释:跑道 2 没有任何障碍,所以不需要任何侧跳。

示例 3:

输入:obstacles = [0,2,1,0,3,0]
输出:2

解释:最优方案如上图所示。总共有 2 次侧跳。

提示:

obstacles.length == n + 1
1 <= n <= 5 * 105
0 <= obstacles[i] <= 3
obstacles[0] == obstacles[n] == 0

2.代码如下:

class Solution {
public:
//思路一:动态规划
/*
    设 d[i][j] 表示青蛙到达i号点的j号跑道时所需要的最少侧跳次数
    如果说j号跑道obstacles[i]-1==j,代表i号j跑道上有石头,所以距离无穷;
    转移方程:
    1. d[i][j]=d[i-1][j]  if j!=bostacles[i]-1; i处该跑道位置没有石头
    2. d[i][j]=inf  if j==bostacles[i]-1;   i处该跑道位置有石头,那就不可能到这个点
    3. d[i][j]=min(d[i][j],mid(d[i-1][0],d[i-1,2],d[i-1][1])+1);
    
*/


public:
    int minSideJumps(vector<int> &obstacles){
        vector<vector<int>> d(obstacles.size(),vector<int>(3,0));
        //这里初始化的原因是因为青蛙原本是在2跑道
        d[0][0]=1;
        d[0][1]=0;
        d[0][2]=1;
        for(int i=1;i<=obstacles.size()-1;i++){
            for(int j=0;j<3;j++){
            //首先考虑前一点也在同一跑道的情况;得到更新的d[i][j]
                if(obstacles[i]-1==j){
                    d[i][j]=INT_MAX;;
                }
                else{
                    d[i][j]=d[i-1][j];
                    }
                }
            //考虑的是从另外的跑道侧跳过来的情况与同一跑道的综合情况,更新最小d[i][j]
            for(int j=0;j<3;j++){
                if(obstacles[i]-1!=j){
			//为什么这里min里面有三个跑道的情况,从另外两个跑道侧跳不是应该只有两个比较吗?
			//因为三个为了适配三种情况,同时因为有d[i][j]共同参与比较,所以该道d+1不可能被选上;
                    d[i][j]=min(d[i][j],Min(d[i][0],d[i][1],d[i][2])+1);
                }
            }

        }
        return Min(d[obstacles.size()-1][0],d[obstacles.size()-1][1],d[obstacles.size()-1][2]);
    }
    int Min(int x,int y,int z){
        int temp=min(x,y);
        return min(temp,z);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_panbk_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值