2025B-多段线数据压缩-100分

刷题笔记合集🔗

问题描述

小基是一名地理信息系统工程师,他需要处理大量的多段线数据。多段线是由一系列连续的点构成的,每个点都有 坐标。由于数据量太大,小基需要对这些多段线数据进行压缩,以减少存储空间和传输带宽。

压缩的原理是:如果三个连续的点在同一条直线上,那么中间的点就是冗余的,可以被删除。具体来说,对于连续的三个点 ,如果满足 ,则认为这三个点共线,可以删除中间点

请你帮助小基实现这个多段线压缩算法,计算压缩后剩余的点的数量。

输入格式

第一行包含一个整数 ,表示多段线中点的数量。

接下来 行,每行包含两个整数 ,表示第 个点的坐标。

输出格式

输出一个整数,表示压缩后剩余的点的数量。

样例输入1

5
1 1
2 2
3 3
4 4
5 5

样例输出1

2

样例输入2

7
1 1
2 2
3 3
4 3
5 2
6 1
7 0

样例输出2

3

样例输入3

6
1 1
2 2
3 3
4 5
5 4
6 6

样例输出3

6

样例解释

样例 解释说明
样例1 所有5个点都在同一条直线上,只需要保留第一个点(1,1)和最后一个点(5,5),其余点都可以删除。因此压缩后剩余2个点。
样例2 这7个点形成了一个V形,可以分为两段直线:(1,1)-(2,2)-(3,3)和(3,3)-(4,3)-(5,2)-(6,1)-(7,0)。第一段直线上的3个点共线,只需保留端点(1,1)和(3,3);第二段直线上的5个点也共线,只需保留端点(3,3)和(7,0)。因此压缩后剩余3个点:(1,1)、(3,3)和(7,0)。
样例3 这6个点不存在三点共线的情况,因此无法压缩,保留所有6个点。

数据范围

题解

这道题目要求我们实现一个多段线压缩算法,核心思想是删除那些与相邻点共线的中间点。

首先,我们需要理解判断三点共线的数学原理。对于三个点 ,它们共线的条件是:

这个公式实际上是通过叉积来判断三点是否共线。如果叉积为0,则三点共线。

解题思路如下:

  1. 如果点的数量小于3,则无法进行压缩,直接返回原始点的数量。
  2. 创建一个新的点集,初始时包含第一个点(起点)。
  3. 从第二个点开始遍历,对于每个点,判断它是否与前一个点和下一个点共线。
    • 如果共线,则跳过该点(即不将其添加到新的点集中)。
    • 如果不共线,则将该点添加到新的点集中。
  4. 最后一个点(终点)始终保留。
  5. 返回新点集的大小,即压缩后剩余的点的数量。

需要注意的是,我们需要连续地应用这个压缩过程,直到无法再压缩为止。这是因为删除一些点后,可能会出现新的三点共线的情况。

时间复杂度分析:

  • 在最坏情况下,我们需要对每个点进行多次判断,时间复杂度为
  • 但在实际应用中,由于大多数点不会被删除,时间复杂度通常接近

空间复杂度分析:

  • 我们需要存储原始点集和压缩后的点集,空间复杂度为

对于给定的数据范围(),这个算法的效率是完全可以接受的。

参考代码

def is_collinear(p1, p2, p3):
    """判断三点是否共线"""
    # 计算叉积:(y3-y1)*(x2-x1) - (y2-y1)*(x3-x1)
    return (p3[1] - p1[1]) * (p2[0] - p1[0]) == (p2[1] - p1[1]) * (p3[0] - p1[0])

def compress_polyline():
    """压缩多段线"""
    # 读取点的数量
    n = int(input())
    
    # 如果点的数量小于3,无法压缩
    if n < 3:
        return n
    
    # 读取所有点的坐标
    points = []
    for _ in range(n):
        x, y = map(int, input().split())
        points.append((x, y))
    
    # 压缩多段线
    compressed = [points[0]]  # 起点始终保留
    
    i = 1
    while i < n - 1:
        # 如果当前点与前一个点和后一个点共线,则跳过该点
        if is_collinear(compressed[-1], points[i], points[i + 1]):
            i += 1
            continue
        
        # 否则,将当前点添加到压缩后的点集中
        compressed.append(points[i])
        i += 1
    
    # 终点始终保留
    if n > 1:
        compressed.append(points

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

算法刷题笔记 文章被收录于专栏

本专栏收集并整理了一些刷题笔记

全部评论

相关推荐

高考出分的那天,我没有哭,也没有笑。手机屏幕上跳出的那个数字,没有惊天动地,也没有波澜壮阔,却像一道闷雷,在我的世界里缓缓滚过。十二年的求学生涯,从农村的土路一路走到城市的水泥地,我不止一次幻想过那天的场景:我会不会激动得落泪,会不会兴奋到跳起来?可真正那天来临时,我却只是平静地点开网页,读完分数,默默放下手机。我是12年上的初中,一个县城的县中,每天清晨五点半起床,五点五十准时跑操,六点零五开始早读。晚上九点半放学,回家后再复习、写作业,常常要到十一点半才能躺下,睡眠时间只有六个小时。高中上的是省重点,一群来自四面八方的尖子生聚集在一起,竞争更加激烈。学校晚自习延迟到了十点半,回家后依然要学习,接近十二点才睡,每天的睡眠变成了五个半小时。在那里,每年都有听说某个学生因压力过大选择了极端的方式,那些沉重的消息像乌云一样笼罩着校园,而我们都低着头,只敢在深夜崩溃。在那样的环境中,分数成了衡量一切的标准。父母却对我没有过高的期望给我压力,他们只希望我能“考个一本”,这句话我听了很多年,几乎成了我脑海里唯一的目标。等到分数出来,我高出一本线近50分,不算耀眼,但足够圆满。对我来说,这是努力与命运达成的一种和解。那一刻,仿佛十多年压在身上的压力,在一瞬间找到了出口,不是泪水,而是彻底的沉静。那天之后,我没有像别人那样疯狂庆祝,只是难得地睡了一个午觉,没有人来打扰,没有梦,醒来时天已经黑了。我终于可以不再设闹钟、不再数睡眠时间、不再靠咖啡续命,终于可以把“高考”从背上卸下,像卸下一块沉重的石头。后来我录取上一所省内不错的大学,城市很大,人生也开始走上新的轨道。回望那年夏天,高考出分的那一天,就像一次告别,告别了过度压抑的青春,也告别了那个不敢停下来的自己。
blitz@0725:22届,那很幸福了
高考出分的那一天,我__
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务