CSDN周赛68期简要题解

判断题有点纠结。一开始选择错误,直到看到原文中一句话:“我们可以将上面一组数字(指上文脉冲编码)做一个等价的变换(指后文增量编码)”,所以增量编码是无损的。此外该章节也提到 “取对数编码” “符合语音信息和图像信息的特点”,以及 “语音质量的差别几乎听不出来”,所以综合起来,感觉题干中 “近乎无损” 的说法应该是正确的,于是在交卷前改了答案。

选择题不难,MP3 / MP4 / JPG 都是影、音、像文件格式,根据原文的意思,必然用到压缩,而文本文件 TXT 在本节压根就没被提到。第二题的 “高频采样” 也是一样没提到过。

填空题也是简单的计算。原文提到 6 比特可以表示 -32~31 的增量,根据二进制的特点,每增加一个比特位就翻一倍,所以要想表示 -250~250,就需要再加 3 个比特位(2^3),答案是 9 。

编程题

第一题 小球游戏

64期刚刚写过,不再赘述。

第二题 王子闯闸门

波斯王子要去救被贾法尔囚禁的公主,但贾法尔用黑魔法在他面前设置了编号从1到n的n道闸门。从王子的位置到1号闸门需要1秒,从n号闸门到公主所在的位置也需要1秒,从p号闸门到p+1或p-1号闸门都需要1秒。
每过1秒钟,王子都必须决定选择前进一道闸门、后退一道闸门或停在原地这三种动作中的一种。当然,王子不能选择移动到关闭状态的闸门而只能选择开启状态的闸门。在王子做出动作选择后,闸门也可能会有关闭和开启的动作,如果王子做完动作后,其所在的闸门在该秒内的动作是从开启变为关闭则他就会被闸门夹死。
现在给出闸门数量n和m个闸门的动作时刻表,求波斯王子需要多少秒才能救出公主。

输入描述:第一行给出n和m,接下来的m行每行代表一个闸门关闭的时段,包含三个数字a、b、c代表编号为a的闸门会在第b秒到第c秒之间关闭,其他时间开启。可能会给出同一编号闸门的多个关闭时段,但这些时段不会相交,即如果给出的数字是a、p、q和a、x、y则不可能p<x<q或x<p<y。

输出描述:波斯王子救出公主所需要的秒数t(t>0)。

输入样例:

2 2
1 2 3
2 1 2

输出样例:

6

AC 本题有运气的成分,虽然思路大致正确,但代码有 bug,所以不提供代码分享。

谈一下我的看法吧。

本题如果把时间看成一个维度,就可以转换成 “走迷宫” 的题型。比如样例,如果把闸门作为纵坐标(行),时间作为横坐标(列),可以得到下面的 “迷宫” 。

 “迷宫” 中绿色的部分不能通行(闸门关闭的时间段),王子起始位置在左上角( 0 行 0 列)公主在最下面一行(n+1 行,任意列)。王子每次只能向右上、右、右下这三个方向移动一格(因为时间只能前进),只要到达最下面一列就算成功救出公主。题目问的就是王子到达 n+1 列时,最小的横坐标(时间)。

所以样例的答案是 6 。

迷宫求最短路径,最常用的是广度优先搜索 bfs 。从王子的初始位置向右上、右、右下三个方向扩散,最先到达 n+1 列的就是最短路径。代码很好写,但是试了一下,超时。加了 n 的限制数量后,也只能通过 40%。显然朴素广搜效率太低,但至少说明题意理解正确。

重新观察题目,不难看出右上、右、右下三个方向中,如果右下方能走出迷宫,花费的时间必然是最短的,其次是右、最后才是右上。由于题目保证一定能走出迷宫,遂将广搜 bfs 改为带递归的深搜 dfs,先朝右下走,一条路走到黑。这时才发现本题的坑在哪里:报错递归深度超出限制,把限制改为极大也不行,说明路径的选择太多。

由于本题没有标注数据范围,实测时才发现,不管是纵向的 n,还是横向的时间序列,都存在极大的 “空白区”。

比如纵向的 n 道闸门里,存在不少连续的闸门是没有关闭时间的,如下图:

而在横向的时间坐标里,也存在一些闸门的关闭时间相当长(1e9 级别)

在这种情况下,对于没有关闭时间的闸门,和关闭时间过长的闸门,就做不到、也没有必要一个坐标一个坐标的去试了。于是要对深搜算法进行优化(本质还是走迷宫,所以搜索算法少不了),将这些 “空白区” 的路径进行压缩。

我采用的办法是:

  • 纵向
    1. 逐个闸门检查;
    2. 如果闸门有关闭时间,则暂时跳过,记录王子的位置在此道闸门前;
    3. 如果遇到某个闸门没有关闭时间,则先通过深搜计算王子从上一步的位置移动到这个闸门的最短时间;
    4. 如果遇到连续闸门都没有关闭时间,则不用搜索,时间直接加上闸门的数量(相当于一直向右下方移动),直到遇到有关闭时间的闸门;
    5. 遇到闸门有关闭时间,返回第 2 步;
    6. 循环反复,直到王子到达 n+1 行。
  • 横向
    1. 只记录闸门关闭的起始时间;
    2. 判断王子当前位置最近的闸门关闭时间(如果当前闸门无关闭时间,则记为无穷大),记为 limit;
    3. 查找王子下一道闸门最近的开启时间,记为 t;
    4. 如果 t 小于 limit,则可以向下道闸门移动,记录位置,递归深搜;
    5. 如果死胡同,则返回第 3 步,查找下一个开启时间;
    6. 如果下一道闸门所有开启时间的通道都是死胡同,则返回上一道闸门。

赛中,我本没有写第 6 步,也是抱着试试看的心理,打赌题目所有的路径不需要返回,也就是王子不需要往右上方移动就能到达最后一行,这样就通过了 90% 。最后顺手加了一句向上走的代码,而且只在特定时间点返回上一行(在当前行的 limit 点返回,可以理解为王子如果不回到上一道闸门就要被当前闸门夹死),竟然就 AC 了。——这也是为什么我说代码有 bug,而且这个路径压缩的代码我写得相当丑陋,就不分享了罢。

无责任猜想这一例可能长这样(乱画的):

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

请叫我问哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值