Python解题 - CSDN周赛第15期 - 客栈的咖啡

news2024/11/26 18:54:04

本期遇上官方大放水,四道题里有三道都在每日一练里做过,再加上比赛时间不太友好,参与人数不多,问哥竟然混了个第一名,真是惭愧。。。就当是官方在奖励那些平时多多参加每日一练的童鞋们了。


第一题:求并集

由小到大输出两个单向有序链表的并集 如链表 A {1 -> 2 -> 5 -> 7} 链表 B {3 -> 5 -> 7 -> 8} 输出: {1 -> 2 -> 3 - > 5 -> 7 -> 8} 。

示例1
输入

4 4

1 2 5 7

3 5 7 8

输出1 -> 2 -> 3 - > 5 -> 7 -> 8

分析

大水题,真没啥好分析的,就是两个列表合并排序,去重。使用python的列表合并、转集合去重、再转列表排序输出,就pass了。

要吐槽的是最后的输出格式,给的示例是要在每个数字之间添加“ -> ”的符号,结果自测默认的结果里“->”左右却没有空格,所以使用自测对比的童鞋估计会怀疑很久。。。

参考代码1

list_a = list(map(int, input().split()))
list_b = list(map(int, input().split()))
print(" -> ".join(map(str, sorted(set(list_a + list_b)))))

当然,可以看到上面代码虽然简单,但对列表的遍历了好几遍。因为python力图将一些基本功能放进黑盒子(内置函数),使代码整体变得优雅,但牺牲了一些效率(虽然对本题没有影响)。如果想深入思考更进一步,本题可以借鉴归并排序的思路,对两个列表排序后依次加入新的列表:

参考代码2

list_a = list(map(int, input().split()))
list_b = list(map(int, input().split()))
list_a.sort() # 默认给的是排好序的列表,所以其实不用排序,只是注明要对升序列表进行此操作
list_b.sort() # 同上
i = j = 0
res = []
while i<len(list_a) and j<len(list_b):
    if list_a[i] < list_b[j]:
        res.append(list_a[i])
        i += 1
    elif list_a[i] > list_b[j]:
        res.append(list_b[j])
        j += 1
    else:
        res.append(list_a[i])
        i += 1
        j += 1
res.extend(list_a[i:])
res.extend(list_b[j:])
print(" -> ".join(map(str, res)))

第二题:小T找糖豆

已知连续序列A,包含1e18个元素,分别是[1,1e18]。 现在去除序列中的n个元素. 得到新的连续序列[X,1e18],该序列中最小元素是?

示例1示例2
输入

3

1 2 3

4

3 5 6 8

输出49

分析

超级大水题。一开始问哥还在纳闷题目什么意思,结果是脑筋急转弯,谜底就在谜面上。。。

题目所谓的[1, 1e18]的大数组不可能真的用内存开出来,所以我们只要找到给出的几个数字里最大的数字,这个数字右边相邻(加一)的数字,就是新的分割后的[x, 1e18]数组里最小的数字。因为新的数组里的数字也要连续,所以分割的左边以及中间那些部分就全都舍弃了。(比如示例2里,4个数字可以分成[1, 2],[4],[7],[9, 1e18],只取[9, 1e18]作为新的序列)

代码就一句话的事。。。

参考代码

n = int(input())
arr = list(map(int, input().split())
print(max(arr) + 1)

第三题:争风吃醋的豚鼠

N个节点两两建边。不存在3个节点相互之间全部相连(3个节点连接成环) 。最多能建立多少条边?

示例

示例1示例2
输入

4

5

输出46

分析

本题就在不久前在每日一练中遇到过,也有点脑筋急转弯的意思。题目描述有点绕,但其实就是问n个节点如果不准连成三角形的话可以连出多少条边。

如下图就可以简单列出当节点个数分别是2到5的时候,可以连出哪些合法边。注意图中黄色点状线表示无法成立的边,因为会使某三个点构成一个三角形:

大家都知道,给出n个节点,如果没有任何限制的话,相互连接组成full mesh,可以有n(n-1)/2条边,表示每个节点(n)都和除了自己以外的其他所有节点(n-1)构成一条边。按照这个思路,我们可以模拟每个节点和其他节点组边的过程。如果把上图最右边5个节点的图摊平来看:

很明显可以发现,为了避免形成三角形,每个节点,向其他节点组边的时候,除了相邻的节点(上图中水平的边),其他节点都需要跳过一个节点才能组边。

  • 节点1:和节点2组边、跳过节点3、和节点4组边、跳过节点5
  • 节点2:和节点3组边、跳过节点4、和节点5组边
  • 节点3:和节点4组边、跳过节点5
  • 节点4:和节点5组边

那么,如果我们增加节点数会看到什么呢?比如有9个节点摊平互连,按照上述规律对每个节点向其右边的节点组边的话,我们就得到了下面这张图。

  • 节点1右边与其能够构成合法边的节点为:2、4、6、8
  • 节点2右边与其能够构成合法边的节点为:3、5、7、9
  • 节点3右边与其能够构成合法边的节点为:4、6、8
  • 节点4右边与其能够构成合法边的节点为:5、7、9
  • 节点5右边与其能够构成合法边的节点为:6、8
  • 节点6右边与其能够构成合法边的节点为:7、9
  • 节点7右边与其能够构成合法边的节点为:8
  • 节点8右边与其能够构成合法边的节点为:9

发现规律了没?从左到右遍历每个节点,每个节点和其右边节点所能构成的边的数量就等于其右边节点数量的一半(向上取整),然后将所有节点能够构成的合法边的数量累加即可。之所以向上取整,是因为当右边节点数量为奇数时,当前节点恰好和最右边的节点可以构成合法边(比如节点2和节点9)。

于是,我们的代码也就呼之欲出了:

参考代码

n = int(input())
result = 0
for i in range(1, n+1):
    result += (n-i)//2 + bool((n-i)%2) # 向上取整
print(result)

向上取整可以使用math模块里的ceiling()函数,但问哥习惯借助python语言里布尔值可以直接参与数学运算的特点,有余数则加一,没有则加零。

当然本题还可以继续深入,找出通用的数学公式,但原理大同小异,不再赘述。


第四题:选择客栈

丽江河边有 n 家很有特色的客栈,客栈按照其位置顺序从 1 到 n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p 。 他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p 元的咖啡店小聚。

第一行三个整数 n, k, p,用空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;

接下来的 n 行,每行两个整数,空格隔开,分别表示客栈的装饰色调和咖啡店的最低消费。

示例:

示例
输入

5 2 3

0 5

1 3

0 2

1 4

1 5

输出3

分析

本题是洛谷原题,但问哥首次遇到这道题还是在CSDN的每日一练里。检查了一下参数都没有变化,就直接套上之前做此题的思路了。(问哥也推荐大家在做题的时候不要一上来就翻题解,先自己思考,结合以前学习到的知识,去试着找到思路,这样印象会更深。)

问哥之前做此题时,首先想到的也是暴力穷举。拿示例举例,5个客栈、2种色调、最高消费3,那这矫情的两人能喝得起咖啡的地方只有客栈2(最高消费3)和客栈3(最高消费2),于是就在这个位置穷举其左右两边(包括自己)有多少对相同色调的客栈。可以看到,符合要求的客栈分别是客栈1与客栈3、客栈2与客栈4、客栈2与客栈5,共三种可能的组合,答案就是3。

当然,数据量小的时候穷举完全可行,但是作为比赛的压轴题,不太可能靠穷举就能过关。于是,这样写代码的话一定会爆。而且由于问哥是在CSDN的每日一练里刷到此题,而每日一练还贴心地提示了本题属于动态规划的范畴,所以一定有更好的解法。

于是,为了找到规律,问哥还是老办法,将客栈的位置画在纸上:

我们来模拟这俩人选客栈的过程,假设他俩从左向右依次遇到客栈。

当遇到第一间客栈时,其咖啡馆的最低消费是5,高于他们的预算3,而且一个客栈也住不下他俩(矫情),但是也许后面可以住到,于是他们在小本本上记下遇到配色0的客栈1间,但是因为没有合适的咖啡馆,所以(暂)不可选,记为0,而题目要求找的可选的客栈自然也是0对(只有1间)。

于是,他们继续向右走,遇到第二间客栈时,发现该客栈的咖啡馆最低消费3,刚好符合他们的要求,但是配色不一样,于是记下新发现了配色1的客栈1间,由于咖啡馆符合要求,所以配色1的客栈符合住的条件,而同样地,由于找到这间咖啡馆,使得之前遇到的配色0的客栈也符合住的条件了(重要),所以修改小本本的记录如下图中所示。代表的含义为:如果后面再遇到同样配色的客栈,那么对应配色可选的客栈数量都记在表里了。

继续往右走,他们遇到第三间客栈,配色是0,于是,找到小本本中记录的同样配色0的可选客栈数为1,所以这一对客栈符合条件,答案更新为1。

然后,因为后面还有客栈,他们想知道总共有多少对,所以需要继续更新表格,于是配色0的客栈数更新为2,而可选客栈数呢?这时他们发现这家客栈的咖啡馆最高消费为2,低于他们的预算3,甚喜,很显然,这间客栈和右边还没遇到的客栈也可以配对,于是两间配色0的客栈都可选(都可以与右边客栈配对),数字更新为2。

继续往右走,这二人遇到的第四间客栈配色为1,于是翻看小本本,发现表中记录了前面遇到过的配色1的客栈有一间是可选的,正好可以和现在这间配对,于是答案更新为2。

但是,由于该客栈的咖啡馆太贵了,超出他们的预算,使得这家客栈不能成为右边客栈的备选,所以可选的配色1的客栈数量还是没有变化。(意味着可以和右边的相同配色客栈配对的客栈数量没有变化)。

到了最后一间客栈,发现配色还是1,于是翻看小本本,发现配色1的可选客栈数量还是1,于是加上1就得到了最终的答案:3。因为是最后一间客栈,理论上他们不需要再更新小本本了,但是他们的强迫症(代码一致性)犯了,打听了咖啡馆的最低消费,发现并不符合条件,于是将表格更新如下图:

我们总结一下:

  1. 首先,我们建一张二维表,横纵坐标分别表示客栈的配色方案与该配色的总客栈数及可选客栈数。然后,我们从左向右遍历客栈列表。
  2. 遇到新的客栈,先查表,检查和当前客栈同样配色的客栈里有多少符合配对条件的客栈,加上答案。
  3. 再更新已经遇到的该配色方案的客栈总数(加上当前客栈)。
  4. 最后检查该客栈里咖啡馆的最低消费,如果高于预算,则不管。
  5. 如果该客栈咖啡馆的最低消费不高于预算,符合条件,则更新之前遇到的所有配色方案的客栈为可选。(修改可选客栈数等于总客栈数)
  6. 继续下一间客栈,重复上面步骤2到5,直到最后。

至此,本题就已经解出90%了。然而,上面例子里还漏掉了一种情况。那就是如果连着遇到好几个配色相同的客栈,却没有遇到符合条件的咖啡馆,直到遇到符合条件的咖啡馆后,所有之前的咖啡馆全变成可选了。在这种情况下,我们要更新的答案需要加上之前同配色的客栈总数,而不是可选客栈数。

比如,如果我们把第二间客栈咖啡馆的最低消费修改为5,高于预算3,那么这二人遇到第三间咖啡馆的时候,左边两间客栈都不可选,但是,由于第三间客栈的咖啡馆符合要求,于是所有遇到过的客栈都可以配对了,答案应该加上客栈总数1(也就是有1对客栈符合条件),然后,再根据上面描述的步骤更新表格。

所以,我们在前面描述的步骤里加上这个条件的判断:

  1. 首先,我们建一张二维表,横纵坐标分别表示客栈的配色方案与该配色的总客栈数及可选客栈数。然后,我们从左向右遍历客栈列表。
  2. 遇到新的客栈,先检查该客栈咖啡馆的最低消费,再查表,如果最低消费高于预算,则把答案加上和当前客栈同样配色的可选客栈数量;如果不高于预算,则加上同样配色的客栈总数
  3. 再更新已经遇到的该配色方案的客栈总数(加上当前客栈)。
  4. 最后再检查一遍该客栈里咖啡馆的最低消费,如果高于预算,则不管。
  5. 如果该客栈咖啡馆的最低消费不高于预算,符合条件,则更新之前遇到的所有配色方案的客栈为可选。(修改可选客栈数等于总客栈数)
  6. 继续下一间客栈,重复上面步骤2到5,直到最后。

根据这个思路写出的代码如下:

参考代码

n, k, p = map(int, input().strip().split())
inn = []
for i in range(n):
    inn.append(list(map(int, input().strip().split())))

res = 0
dp = [[0]*2 for _ in range(k)] # 步骤1
for i in range(n):
    res += dp[inn[i][0]][0] if inn[i][1] <= p else dp[inn[i][0]][1] # 步骤2
    dp[inn[i][0]][0] += 1 # 步骤3
    if inn[i][1] <= p: # 步骤4
        for j in range(k): # 步骤5
            dp[j][1] = dp[j][0]
print(res)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/92412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3响应式原理设计和实现

Vue3响应式原理设计和实现响应式什么是响应式手动响应式proxy代理对象响应式系统一个属性注册一个副作用函数一个属性注册多个副作用函数多个属性注册不同的副作用函数多个数据不同属性注册不同的副作用函数响应式 什么是响应式 响应式是一个过程&#xff0c;这个过程存在两个…

【MaixPy】:K210识别简例(简单二维码检测和双二维码检测)

实物图 俩二维码识别实物图 前言 这段时间接触了一下基于MaixPy的开发K210的摄像头设备,的确很有趣,运行速度很快,编程难度不大。很适合咱们视觉开发的同学们学习,以下是我玩设备的一些感悟,如有不妥之处,希望大家雅正,也希望能帮助初学者了解和学习,也可加bulidupup(…

java毕业设计——基于java+Socket+sqlserver的网络通讯系统设计与实现(毕业论文+程序源码)——网络通讯系统

基于javaSocketsqlserver的网络通讯系统设计与实现&#xff08;毕业论文程序源码&#xff09; 大家好&#xff0c;今天给大家介绍基于javaSocketsqlserver的网络通讯系统设计与实现&#xff0c;文章末尾附有本毕业设计的论文和源码下载地址哦。 文章目录&#xff1a; 基于jav…

LwIP源码分析(3):内存堆和内存池代码详解

文章目录1 内存堆1.1 mem_init1.2 mem_malloc1.3 mem_free2 内存池2.1 memp_init2.2 memp_malloc2.3 memp_free3 内存管理宏定义在嵌入式系统中&#xff0c;内存池有助于快速有效地分配内存。LwIP提供了两个灵活的方式来管理和组织内存池的大小&#xff1a;内存堆和内存池。当然…

电脑维修记录

记于2022年12月15日 今天把电脑修好了&#xff0c;总结这次经验&#xff1a; &#xff08;1&#xff09;无知者无畏&#xff0c;对任何事情都要抱有探索的精神&#xff0c;最遗憾的事情不是做错了&#xff0c;而是想做没去做 &#xff08;2&#xff09;将每次走错路的经历都…

Orcale数据表去重创建联合主键

分享一下最近遇到的一个问题&#xff0c;我们从一个数据表中将数据表中的数据同步到另一个数据库的表中&#xff0c;由于要同步的数据表中没有建主键&#xff0c;所以数据同步后发现同步的数据比原始数据表中的数据要多&#xff0c;有不少重复的数据。因此需要对数据表进行去重…

事业编招聘:市委社会工委北京市民政局事业单位公开招聘

市委社会工委市民政局所属事业单位 根据《北京市事业单位公开招聘工作人员实施办法》&#xff08;京人社专技发﹝2010﹞102号&#xff09;等文件精神&#xff0c;北京市委社会工委北京市民政局所属21家事业单位面向社会及应届毕业生公开招聘事业单位工作人员88名。现将具体情况…

【SpringBoot 2.x】定时任务 之- @Scheduled注解

一、概述 Scheduled注解是Spring Boot提供的用于定时任务控制的注解&#xff0c;主要用于控制任务在某个指定时间执行&#xff0c;或者每隔一段时间执行。注意需要 启动类加EnableScheduling实现类加Component方法上加ScheduledScheduled主要有以下几种配置执行时间的方式&…

Neural Discrete Representation Learning (VQ-VAE) 简介

目录VQ-VAE参考VQ-VAE VAE是一种生成模型。 Vector QuantisedVariational AutoEncoder (VQ-VAE)是VAE的变种&#xff0c;其隐含变量是离散的。离散的隐含变量对于自然语言&#xff0c;推理都比较有帮助。著名的DALL-E就使用了类似VQ-VAE的离散隐含变量来从文本生成图像&#x…

【Python】同一网络下,手机和电脑进行socket通信

同一网络下&#xff0c;手机和电脑进行socket通信 最近在学python网络编程&#xff0c;发现socket可以进行跨主机的进程通信&#xff0c;于是尝试用电脑作为服务端&#xff0c;手机作为客户端&#xff0c;来进行socket通信。 电脑端准备 1.电脑开启热点&#xff08;非必须&a…

[附源码]Python计算机毕业设计SSM基于vue的图书管理系统2022(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

java递归实现多级Map集合合并(结合实际场景)

合并Map集合 合并Map集合有很多方法&#xff0c;例如Map自生提供的putAll()方法。但是这种方法只能合并一层的集合&#xff0c;如果是多层的呢&#xff1f; 场景 现在有一个yml配置文件&#xff0c;由于项目部署在多台服务器上&#xff0c;而且每台服务器上的配置有些许差异…

Ajax(四)

1.模板引擎 1.1 模板引擎的基本概念 1.2 什么是模板引擎 不需要再用字符串拼接 1. 3模板引擎的好处 1.4 art-template模板引擎 art-template 是一个简约、超快的模板引擎。 中文官网首页为 http://aui.github.io/art-template/zh-cn/index.html 1.4.1 art-template模板引擎的…

为什么Python现在这么火?

Python可以说是目前最火的网红编程语言&#xff0c;虽然它在近几年在逐渐流行起来&#xff0c;但其实它已经发展了近三十年。那么&#xff0c;为什么Python现在这么火呢&#xff1f;一方面人工智能和大数据的崛起带红了Python&#xff0c;另一方面无论是软件开发者还是非编程工…

抗肿瘤的靶向药物——艾美捷西妥昔单抗Cetuximab说明

近年来恶性肿瘤极大的治疗进展是靶向新药的开发与使用。表皮生长因子受体EGFR是一种具有酪氨酸激酶活性的跨膜受体&#xff0c;受表皮生长因子EGF和转化生长因子-α(TGF-α)的刺激。多种肿瘤细胞株过度表达EGFR&#xff0c;包括25%&#xff5e;80%的结直肠癌CRC细胞。 西妥昔单…

RSS Can:使用 Golang Rod 解析浏览器中动态渲染的内容:(四)

第四篇文章&#xff0c;来聊聊 Golang 生态中如何“遥控”浏览器&#xff0c;更简单、可靠的使用基于 CDP &#xff08;Chrome DevTools Protocol&#xff09;协议的浏览器作为容器&#xff0c;获取诸如微博、B 站 这类动态渲染内容信息&#xff0c;将它们转换为 RSS 订阅源。 …

【C语言进阶】不会处理字符串?一万三千五百字包会保姆级教程

目录 &#x1f618;前言&#x1f618;&#xff1a; 一、字符串处理函数介绍&#x1f92f;&#xff1a; 1.strlen 函数&#x1f94e;&#xff1a; 2.strcpy 函数⚾&#xff1a; 3.strcat 函数&#x1f3c0;&#xff1a; 4.strcmp 函数&#x1f3c8;&#xff1a; 5.strncpy 函数…

WSL_03 WSL2 从C盘迁移到D盘

文章目录1 动机1 查看虚拟机状态&#xff0c;并关闭要迁移的虚拟机2 迁移WSL22.1 出现的问题&#xff1a;已存在具有提供的名称的分发(已解决)3 设置启动时的默认用户&#xff0c;没有设置默认为root参考1 动机 WSL2默认安装在C盘中&#xff0c;win R运行中使用%localappdata…

python科学计算 之 Numpy库的使用详解

目录 一&#xff1a;Numpy简介 二&#xff1a;ndarray的创建 三&#xff1a;ndarray的属性 四&#xff1a;切片 索引 五&#xff1a;数组的轴(二维数组) 六&#xff1a;二维数组 切片索引 七&#xff1a;高级索引 八&#xff1a;Numpy广播 九&#xff1a;ufunc函数 算…

使用pypy来提升你的python项目性能

一、PyPy介绍 PyPy是用Python实现的Python解释器的动态编译器&#xff0c;是Armin Rigo开发的产品&#xff0c;能够提升我们python项目的运行速度。PyPy 是利用即时编译的 Python 的替代实现。背后的原理是 PyPy 开始时就像一个解释器&#xff0c;直接从源文件运行我们的 Pyth…