第 15 题
答案与解析
第(1)小题
4,6
系统省略每次连续跑步的最后一次打卡,因此记录中的每个编号k都表示已跑过k至k+1的路段。判断是否完成任务,只需检查1—2、2—3、3—4、4—5、5—6五段是否全部覆盖;重复记录不会增加新的覆盖路段。
| 学生编号 | 合并后的已完成路段 | 未完成路段 |
|---|---|---|
| 1 | 1—4、5—6 | 4—5 |
| 2 | 1—2、3—6 | 2—3 |
| 3 | 1—3、4—6 | 3—4 |
| 4 | 1—6 | 无 |
| 5 | 1—3、4—6 | 3—4 |
| 6 | 1—6 | 无 |
4号虽然先记录2、3、4、5,再记录1,但这些记录已覆盖全部五段;6号连续记录1至5,也覆盖全部路线。
第(2)小题
2
程序分析
res=t[0]*10
p=1; j=1
while j<len(t):
if t[j]-t[j-1]==p:
...
else:
...
j+=1res初值的十位是第一条记录,个位为0;j从1开始,检查后续记录。循环中会删除列表元素,因此每轮都按当前列表长度判断,不能按原列表的固定下标逐次推演。
if t[j]-t[j-1]==p:
res=res//10*10+t[j]
t.pop(j)
j-=1
p+=1条件成立时,res保留十位的区段起点,把个位改为当前记录;随后删除当前元素,区段起点仍留在t[j-1]的位置。j先减1再由循环末尾加1,使下一条移到此位置的记录仍被检查。
每合入一条连续记录,p加1。例如起点3之后合入4并删除4,下一条应与保留的起点3相差2,而不是与已删除的4相差1。因此p表示当前连续记录段的记录数,也是下一条连续记录与起点应有的差值。
else:
if p==1:
t[j-1]=res+res//10+1
else:
t[j-1]=res+1
res=t[j]*10
p=1不满足连续条件时,结束当前记录段并将其压缩为两位数:十位是起点,个位是实际跑到的终点。若只有一条记录s,res=s×10,写入res+res//10+1即s×10+s+1,表示s至s+1;若已有连续记录,res个位已是最后一条记录,加1即可补回未记录的终点。然后以当前t[j]开始新的一段,p重新置1。
if p==1:
t[j-1]=res+res//10+1
else:
t[j-1]=res+1
return t循环结束后,最后一段尚未遇到“不连续”的下一条记录,故再按同一规则完成末段压缩,返回修改后的列表。
对t=[3,4,4,5,1],依次检查如下。表中的j、p均为本轮判断时的值:
| j | p | 判断 | 本轮处理后的t | 加框语句累计次数 |
|---|---|---|---|---|
| 1 | 1 | 4−3=1,成立 | [3,4,5,1] | 1 |
| 1 | 2 | 4−3=1≠2 | [35,4,5,1] | 1 |
| 2 | 1 | 5−4=1,成立 | [35,4,1] | 2 |
| 2 | 2 | 1−4=−3≠2 | [35,46,1] | 2 |
第一轮删除的是第一个4;第二个4与起点3的差仍为1,不满足此时p=2的要求,因此另起一段。循环结束后,末尾记录1被压缩成12,返回[35,46,12]。加框处只在两次连续条件成立时执行,共2次。
第(3)小题
a[p]%10<a[p+1]%10
p+=1
rsu=sortv(stu[i])
程序分析
n=len(stu)
for i in range(n):
stu[i]=orga(stu[i])
③
ans=""
for j in range(len(rsu)-1):
ans+=str(rsu[j]%10)+'-'+str(rsu[j+1]//10)+','
if ans=="":
print(i+1,'号学生完成跑步任务')
else:
print(i+1,'号学生未完成路段:',ans[:-1])主程序逐个处理学生。orga将该生记录转为区段编码,例如[35,46,12]表示3—5、4—6、1—2。后续遍历rsu,把前一区段的终点与后一区段的起点组成未完成路段,因此③需要得到按起点排列、已合并相交或相接区段的结果,而不能直接沿用尚未整理的编码列表。
def sortv(a):
p=0; i=0
while i<len(a) and p<len(a)-1:
j=len(a)-1
while j>i:
...
if a[p]%10>=a[p+1]//10:
...
elif i!=0:
②
i+=1
return a进入sortv后,i、p均从0开始。外层每轮先进行一趟排序,再检查相邻区段能否合并;i逐轮加1,p用于定位本轮比较的相邻区段。函数返回的是经原地修改的列表a。
j=len(a)-1
while j>i:
if a[j]<a[j-1]:
a[j],a[j-1]=a[j-1],a[j]
j-=1j从表尾向左扫描。右侧元素较小时交换相邻元素,使较小的编码不断向左移动,一趟后当前后缀中的最小值到达下标i。这是从右向左进行的冒泡过程。
区段编码的十位为起点、个位为终点,编码升序首先对应起点升序;起点相同时,终点较小的排在前面。
if a[p]%10>=a[p+1]//10:
if ①:
a[p]=a[p]//10*10+a[p+1]%10
a.pop(p+1)
elif i!=0:
②a[p]%10取前一区段的终点,a[p+1]//10取后一区段的起点。前者不小于后者时,两段相交或首尾相接,可以合并。
①成立后,已知赋值保留前一区段的起点,把终点改为后一区段的终点;随后无论①是否成立,都会删除后一区段。是否需要改写终点,必须由两段终点的大小关系决定。若两段分离,则在i!=0时执行②。
填空分析
①
合并后的终点应为两段终点的较大值。只有后一区段终点更大时,才需要执行已有的终点改写语句,故填:
a[p]%10<a[p+1]%10
例如35和46合并时,5<6,前一编码更新为36;若是36和45,后一段完全包含在前一段中,应保持36,仅删除45。两种情况合并后均保持p不变,以便继续检查后续区段。
②
两段分离时,当前区段不能与后一段合并,需要向后移动比较位置,填:
p+=1
原程序保留i!=0这一限制,是因为第0趟排序只保证最小编码到达表首,第二个位置未必已是剩余最小值。此时若发现两段分离,不宜立即跳过表首区段,应在下一趟排序后再检查。
③
orga返回的是压缩后的区段列表,③需要调用sortv完成排序与合并,并把返回值交给后续使用的rsu,填:
rsu=sortv(stu[i])
例如2号学生的编码[35,46,12]整理为[12,36],主程序由前段终点2与后段起点3生成未完成路段2—3。
原主程序的限制:它只检查相邻已完成区段之间的空缺,未检查第一段是否从1开始、最后一段是否到6。例如记录[2,3]压缩并合并后为[24],内部循环不执行,ans为空,程序会误报完成任务,实际仍缺1—2和4—6。这一问题不能由题设三个空的预期填法解决;本题给出的6名学生均覆盖路线首尾,因此不影响这组数据的判定。
问题反馈
解析有疑问或显示异常?请先复制题目信息,再打开反馈表单填写。
题目编号:2026_05_G3_jingchenglianmeng_q015
