2023.12.8每日一题 出租车的最大盈利【!!!】

2008. 出租车的最大盈利

你驾驶出租车行驶在一条有 n 个地点的路上。这 n 个地点从近到远编号为 1n ,你想要从 1 开到 n ,通过接乘客订单盈利。你只能沿着编号递增的方向前进,不能改变方向。

乘客信息用一个下标从 0 开始的二维数组 rides 表示,其中 rides[i] = [starti, endi, tipi] 表示第 i 位乘客需要从地点 starti 前往 endi ,愿意支付 tipi 元的小费。

每一位 你选择接单的乘客 i ,你可以 盈利 endi - starti + tipi 元。你同时 最多 只能接一个订单。

给你 nrides ,请你返回在最优接单方案下,你能盈利 最多 多少元。

**注意:**你可以在一个地点放下一位乘客,并在同一个地点接上另一位乘客

首先,注意题目所说,司机一次只能接一个订单

寻找子问题

以 从1开到9 为例,如果我们要计算从1-9要赚多少钱

如果 在 9 没有乘客 下车 或者 没有乘客在车上,

​ 那么就变成了 计算 从1-8 要赚多少钱

如果在 9 有乘客下车,那么我们枚举 在9处下车的订单,哪个赚的最多,如果从5上车到9下车的订单赚的最多

​ 那么就变成了 计算 从 1-5 要赚多少钱

每个地点,我们都考虑, 有或没有

如同上面的思考方式,在每个地点,我们都可以转换 为前面地点,即子问题的考虑,符合状态转移的思想

所以用动态规划来解决

动态规划五部曲

1.确定dp[ i ]的下标和意义:

dp[ i] 代表从0开到i 处的最大盈利

2.确定递推公式:

如果 i处无乘客 下车,

​ 则 dp[ i] =dp[ i-1]

如果i处 有乘客下车 ,那么枚举i处下车的订单得到利润最大的订单j

​ 则 dp[ i] =dp[ rides[j] [0] ] + rides[j] [1]-rides[j] [0] +rides[j] [2]

取两者的max

3.初始化dp

​ 开始无收入,所以都初始化为0

4.确定遍历顺序:

​ dp[i ]是由 dp[ i-1] 和dp [rides[j] [0]] 推导出来的

​ 所以遍历顺序应该从前到后

5.打印

代码

class Solution{
    public long maxTaxiEarnings(int n, int[][] rides) {
        //用map记录每个订单,以下车点为key,方便后面 对下车订单的枚举
        Map<Integer, List<int[]>> record=new HashMap<>();
        for(int ride[]:rides){
            List<int[]>list=record.getOrDefault(ride[1],new ArrayList<>());
            list.add(new int[]{ride[0],ride[2]});
            record.put(ride[1] ,list);
        }
        long[] dp=new long[n+1];
        for(int i=1;i<=n;i++){
            //此地点无乘客下车的情况:no
            long no=dp[i-1];
            //此地点有乘客下车的情况:yes
            long yes=0;
            if(record.containsKey(i)){
                List<int[]> personList= record.get(i);
                for(int[] person:personList){
                    yes=Math.max(yes,i-person[0]+person[1]+dp[person[0]]);
                }
            }
            dp[i]=Math.max(yes,no);
        }
        return dp[n];
    }
}

参考:
灵神题解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值