2023-07-25:你驾驶出租车行驶在一条有 n 个地点的路上

这 n 个地点从近到远编号为 1 到 n ,你想要从 1 开到 n

通过接乘客订单盈利。你只能沿着编号递增的方向前进,不能改变方向

乘客信息用一个下标从 0 开始的二维数组 rides 表示

其中 rides[i] = [starti, endi, tipi]

表示第 i 位乘客需要从地点 starti 前往 endi

愿意支付 tipi 元的小费

每一位 你选择接单的乘客 i ,你可以 盈利 endi - starti + tipi 元

你同时 最多 只能接一个订单。

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

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

输入:n = 5, rides = [[2,5,4],[1,5,1]]。

输出:7。

答案2023-07-25:

maxTaxiEarnings1算法的大体过程如下:

1.对乘客订单rides按照起始地点的编号进行升序排序。

2.调用build函数,构建区间树数据结构,初始化max数组。

3.遍历排序后的rides数组,对每个乘客订单进行处理:

a.根据乘客订单的起始地点,通过maxQuery函数查询当前位置之前的最大盈利额,存储在money变量中。

b.计算当前乘客订单的盈利额,即end-start+tip。

c.将当前乘客订单的结束地点作为索引,更新max数组中对应位置的值,更新为money+当前乘客订单的盈利额。

4.返回maxQuery函数查询整个路程的最大盈利额,即maxQuery(n)。

maxTaxiEarnings2算法的大体过程如下:

1.初始化sorted数组,用于存储所有乘客订单的起始和结束地点,长度为乘客订单数量的两倍。

2.遍历rides数组,将乘客订单的起始和结束地点依次存储到sorted数组中。

3.对sorted数组进行升序排序。

4.对乘客订单rides按照起始地点的编号进行升序排序。

5.初始化dp数组,并将所有元素置为0。

6.初始化dpi变量为0,用于记录当前处理到的sorted数组下标。

7.初始化pre和ans变量为0。

8.遍历排序后的rides数组,对每个乘客订单进行处理:

a.获取当前乘客订单的起始和结束地点。

b.分别使用rank函数查找sorted数组中起始和结束地点的下标。

c.更新dp数组,从dpi到起始地点的下标之间的元素,将其值更新为max(pre, dp[dpi])。

d.计算当前乘客订单的盈利额,即end-start+tip。

e.更新ans变量,取盈利额和当前ans的最大值。

f.将dp数组中结束地点的下标位置的值更新为max(dp[erank], 盈利额)。

9.返回ans变量,即最大盈利额。

这两种算法的核心思想都是通过动态规划来计算每个乘客订单的盈利额,并利用区间树或排序数组来快速查询之前的最大盈利额,从而得到整个路程的最大盈利额。

maxTaxiEarnings1算法的总的时间复杂度为O(nlogn),总的额外空间复杂度为O(n)。

maxTaxiEarnings2算法的总的时间复杂度为O(nlogn),总的额外空间复杂度为O(n)。

go完整代码如下:

package main

import (
"fmt"
"sort"
) const MAXN = 100001 var max = make([]int64, MAXN<<2)
var sorted = make([]int, MAXN)
var dp = make([]int64, MAXN) var n = 0 func build(l, r, rt int) {
if l == r {
max[rt] = 0
} else {
mid := (l + r) / 2
build(l, mid, rt<<1)
build(mid+1, r, rt<<1|1)
pushUp(rt)
}
} func maxQuery(r int) int64 {
if r < 1 {
return 0
}
return maxQueryRange(1, r, 1, n, 1)
} func maxQueryRange(L, R, l, r, rt int) int64 {
if L <= l && r <= R {
return max[rt]
}
mid := (l + r) >> 1
ans := int64(0)
if L <= mid {
ans = max64(ans, maxQueryRange(L, R, l, mid, rt<<1))
}
if R > mid {
ans = max64(ans, maxQueryRange(L, R, mid+1, r, rt<<1|1))
}
return ans
} func update(index int, c int64) {
updateNode(index, c, 1, n, 1)
} func updateNode(index int, c int64, l, r, rt int) {
if l == r {
max[rt] = max64(max[rt], c)
} else {
mid := (l + r) >> 1
if index <= mid {
updateNode(index, c, l, mid, rt<<1)
} else {
updateNode(index, c, mid+1, r, rt<<1|1)
}
pushUp(rt)
}
} func pushUp(rt int) {
max[rt] = max64(max[rt<<1], max[rt<<1|1])
} func maxTaxiEarnings1(len int, rides [][]int) int64 {
sort.Slice(rides, func(i, j int) bool {
return rides[i][0] < rides[j][0]
})
n = len
build(1, n, 1)
for _, ride := range rides {
money := maxQuery(ride[0]) + int64(ride[1]-ride[0]+ride[2])
update(ride[1], money)
}
return maxQuery(n)
} func rank(sorted []int, len int, num int) int {
ans := 0
l := 0
r := len - 1
for l <= r {
m := (l + r) / 2
if sorted[m] >= num {
ans = m
r = m - 1
} else {
l = m + 1
}
}
return ans
} func maxTaxiEarnings2(len0 int, rides [][]int) int64 {
m := len(rides)
j := 0
for i := 0; i < m; i++ {
sorted[j] = rides[i][0]
j++
sorted[j] = rides[i][1]
j++
}
sort.Slice(rides, func(i, j int) bool {
return rides[i][0] < rides[j][0]
})
sort.Ints(sorted[:m<<1])
for i := 0; i < m<<1; i++ {
dp[i] = 0
}
dpi := 0
pre := int64(0)
ans := int64(0)
for _, ride := range rides {
start := ride[0]
end := ride[1]
tips := ride[2]
srank := rank(sorted, m<<1, start)
erank := rank(sorted, m<<1, end)
for dpi <= srank {
pre = max64(pre, dp[dpi])
dpi++
}
money := pre + int64(end-start+tips)
ans = max64(money, ans)
dp[erank] = max64(dp[erank], money)
}
return ans
} func max64(a, b int64) int64 {
if a > b {
return a
}
return b
} func main() {
n := 5
rides := [][]int{{2, 5, 4}, {1, 5, 1}} // n := 20
// rides := [][]int{{1, 6, 1}, {3, 10, 2}, {10, 12, 3}, {11, 12, 2}, {12, 15, 2}, {13, 18, 1}} result1 := maxTaxiEarnings1(n, rides)
result2 := maxTaxiEarnings2(n, rides) fmt.Println("Result from maxTaxiEarnings1:", result1)
fmt.Println("Result from maxTaxiEarnings2:", result2)
}

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

  1. XPath语法 在C#中使用XPath示例 【转http://www.cnblogs.com/yukaizhao/archive/2011/07/25/xpath.html】非常详细的文章

    XPath语法 在C#中使用XPath示例   XPath可以快速定位到Xml中的节点或者属性.XPath语法很简单,但是强大够用,它也是使用xslt的基础知识. 示例Xml: <?xml ve ...

  2. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

  3. 2018.07.25 bzoj3878: [Ahoi2014&Jsoi2014]奇怪的计算器(线段树)

    传送门 线段树综合. 让我想起一道叫做siano" role="presentation" style="position: relative;"&g ...

  4. 2018.07.25 hdu5306Gorgeous Sequence(线段树)

    传送门 线段树基本操作. 要求维护区间取min" role="presentation" style="position: relative;"> ...

  5. DolphinScheduler 线上 Meetup 视频回放(07.25)

    上周六下午 DolphinScheduler 社区联合 Doris 社区进行了 2020 年首次线上 Meetup,各位讲师都做了非常精彩的分享,也吸引了 1900 多位技术伙伴观看. 其中 Dolp ...

  6. 2022.07.25 TypeScript基础类型介绍

    基础类型: 字符串(string)(String) let first: string = 'niu' // 直接赋值 let fourth: string = `niu` // 模板字符串 let ...

  7. BUAA面向对象设计与构造——第二单元总结

    BUAA面向对象设计与构造——第二单元总结 第一阶段:单部傻瓜电梯的调度 第二阶段:单部可捎带电梯的调度 (由于我第一次写的作业就是可捎带模式,第二次只是增加了负数楼层,修改了一部分参数,因此一起总结 ...

  8. OO第三阶段作业总结

    调研:        最早的程序设计是直接采用机器语言来编写的,或者使用二进制码来表示机器能够识别和执行的指令和数据.机器语言的优点在于速度快,缺点在于写起来实在是太困难了,编程效率低,可读性差,并且 ...

  9. TSR交通标志检测与识别

    TSR交通标志检测与识别 说明: 传统图像处理算法的TSR集成在在ARM+DSP上运行,深度学习开发的TSR集成到FPGA上运行. 输入输出接口 Input: (1)图像视频分辨率(整型int) (2 ...

  10. liunx驱动----USB驱动

    现象:把usb设备接入电脑 1.Windows发现设备 2.跳出一个对话框提示安装驱动程序 问1:既然没有驱动程序,为什么了够知道是什么驱动了?? 答1:Windows里面已经有了usb总线驱动程序, ...

随机推荐

  1. MapStruct实体映射转换

    1.MapStruct简介 MapStruct是一个代码生成器,它基于约定优于配置的方法,极大地简化了Java bean类型之间映射的实现.生成的映射代码使用简单的方法调用,快速.类型安全且易于理解. ...

  2. java Stack(栈)类、Queue和Deque队列

    1. java Stack类 特性是:LIFO(后进先出)先进后出,最先进入的在栈底. Stack底层也是通过数组实现的,同时也是线程安全的 Stack stack=new Stack(); //添加 ...

  3. 深度学习-09(目标检测:Object Detection)

    文章目录 目标检测(Object Detection) 一 .基本概念 1. 什么是目标检测 2. 目标检测的核心问题 3. 目标检测算法分类 4. 目标检测应用 目标检测原理 1.候选区域产生 1 ...

  4. 分享Zeal的全套离线文档

    鉴于Zeal自身的下载速度... 为了方便大家,现在把我自己下载好的Zeal离线文档全部分享出来 百度网盘链接:https://pan.baidu.com/s/19WeEWij3evnuMWhzbHu ...

  5. Python NumPy 广播(Broadcast)

    广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行. 如果两个数组 a 和 b 形状相同,即满足 a.shape == ...

  6. 2022-05-05:给定一个正数num,要返回一个大于num的数,并且每一位和相邻位的数字不能相等. 返回达标的数字中,最小的那个。 来自微软。

    2022-05-05:给定一个正数num,要返回一个大于num的数,并且每一位和相邻位的数字不能相等. 返回达标的数字中,最小的那个. 来自微软. 答案2022-05-05: 从左往右看,是否有相邻两 ...

  7. Linux 创建 Python 虚拟环境

    Linux 创建 Python 虚拟环境 0. 前言 网上教程太杂太乱,要么排版不好看,要么讲半天讲不到重点,故做此篇,精简干练. 1. 安装virtualenv 先用pip安装virtualenv第 ...

  8. 为什么 GPU 能够极大地提高仿真速度?

    这里的提速主要是针对时域电磁算法的.因为时域算法的蛙跳推进模式仅对大量存放在固定 位置的数据进行完全相同的且是简单的操作(移位相加),这正是 GPU 这类众核 SIMD 架构所进行的运算,即 ALU ...

  9. HDU - 7125 Master of Shuangpin

    D. Master of Shuangpin time limit per test 1 second memory limit per test 256 megabytes input standa ...

  10. 【LeetCode双向链表】LRU详解,双向链表实战

    LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构. 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity ...