第 15 题
答案与解析
第(1)小题
[3,1]
10:25 到 11:20 涉及 10~11、11~12 两个使用时段。信号 0、1 都表示当前时段无人,信号 2 表示当前有人。
| 使用时段 | 按图 a 判断 | 分配结果 |
|---|---|---|
| 10~11 | 1、2、4 号座位均为红灯,只有 3 号座位为黄灯,当前可用;其下一时段为红灯,连续空闲时段数为 1 | 3 号座位 |
| 11~12 | 3 号座位已不能继续使用,需重新选择;此时只有 1 号座位空闲 | 1 号座位 |
按使用时段顺序记录,安排为 [3,1]。
第(2)①小题
12
程序分析
h.append([0]*n)在信号表末尾增加一行 n 个 0,作为统计的边界行。这一行位于原有时段之后。
for i in range(len(h)-2,-1,-1):
for j in range(n):
if h[i][j]==0 or h[i][j]==1:
h[i][j]=h[i-1][j]+1
else:
h[i][j]=0 #语句1i 从原表最后一行倒序遍历到第 0 行,新增边界行不参与循环;j 遍历各座位。信号 0、1 都表示当前座位无人,进入加框语句;信号 2 表示当前有人,执行语句1,将统计值记为 0。加框语句试图累计连续空闲时段,但题目已指出其中有误,其累计方向需在②中修正。
语句1位于 else 分支,只有当前信号既不是 0 也不是 1,即为红灯信号 2 时才执行。按座位列统计图 a 中的红灯数:
| 座位号 | 红灯时段数 |
|---|---|
| 1 | 4 |
| 2 | 4 |
| 3 | 1 |
| 4 | 3 |
共执行 4+4+1+3=12 次。加框处虽有错误,但它只改写当前 h[i][j];遍历到某个位置时,该位置仍是原始信号,所以不影响该位置是否进入 else 分支。
第(2)②小题
h[i][j]=h[i+1][j]+1
共用程序分析见第(2)①小题。
填空分析
h[i][j]=h[i-1][j]+1
空位统计表要记录“从当前时段开始,向后连续空闲的时段数”。当前信号为 0 或 1 时,本时段可用,连续空闲数应为下一时段的连续空闲数加 1。
循环从最后一个时段向前处理,所以 h[i+1][j] 已经完成统计,而 h[i-1][j] 对应更早时段,尚未处理,不能作为向后的累计依据。加框处应改为:
h[i][j]=h[i+1][j]+1
例如,1 号座位 13~14 时段有人,统计值为 0;12~13 时段空闲,得到 0+1=1;11~12 时段也空闲,得到 1+1=2,与图 b 一致。末尾补入的全 0 行使最后一个开放时段在空闲时得到 0+1=1,不会把关门后的时段算入。
第(3)小题
td=t2-t1
d[i][m]==0
i+=1
程序分析
h=creat(y,st,ed,n) #获取自修室指示灯信号表
d=trans(h) #将指示灯信号表转化为空位统计表先调用第14题的 creat 得到信号表,再使用第(2)题修正后的 trans 得到空位统计表 d。d[i][j] 表示从第 i 行对应时段开始,j+1 号座位连续空闲的时段数;行号 0 对应开门时段 st~st+1。
t1=int(at[:2]) ; t2=int(pt[:2])+1
tot=0 ; res=[] #数组res存储读者各使用时段的座位号
①
flag=True ; i=t1-st
while i<t2-st:
if tot==0:
...
else:
...t1 取到达时刻的小时数,t2 按题给代码取离开时刻的小时数加1。i 从到达时段对应的行号 t1-st 开始,在 i<t2-st 时继续处理。循环按 tot 是否为0分成两步:为0时选择座位,否则为当前时段分配已选座位。res 保存分配结果,flag 初值为 True。
if tot==0:
m=0
for j in range(1,n):
if d[i][j]>d[i][m]:
m=j
if ②:
flag=False
break
tot=d[i][m]tot 为 0 时重新选择座位。m 先取最小列号 0,j 从小到大扫描,只有发现更大的连续空闲数才更新 m,因此相同时保留较小座位号。扫描结束,m 对应当前时段连续空闲数最大的座位。若满足失败条件,则标记并退出;否则把该座位的连续空闲数赋给 tot,下一轮进入分配分支。
else:
res.append(m+1)
if tot>=td:
d[i][m]-=td
else:
d[i][m]-=tot
tot-=1 ; td-=1
③res 追加 m+1,将列下标转换为座位号。接着从当前统计值中减去 tot、td 中较小的一个,表示本段安排占用的连续时段数。每安排一个时段,tot 和 td 都减 1:tot 表示当前座位还可连续使用的时段数,td 表示读者尚未完成分配的时段数。当前座位用完后,tot 变为 0,程序在下一待安排时段重新选座。
if flag==False:
print("座位安排失败!")
else:
print(t1,"~",t2,"中各时段座位安排:",res)若中途标记失败,输出失败提示;否则输出按时段顺序保存的座位号列表。
填空分析
①
td 表示尚需安排的时段数,初值应为本次全部使用时段数。根据题给折算,时段起点从 t1 到 t2-1,共 t2-t1 个,因此填写:
td=t2-t1
本题示例均为非整点离开。若整点离开且不占用离开后的时段,固定语句 t2=int(pt[:2])+1 会多计一个时段;这属于题面时间折算的边界问题,不能只靠本题三个空缺消除。
②
m 已指向当前时段连续空闲数最大的座位。若最大值 d[i][m] 仍为 0,说明当前所有座位都不可用,应分配失败;只要大于 0,就可以先安排该座位,之后再按规则处理剩余时段。因此填写:
d[i][m]==0
③
else 分支已经为当前时段追加了一个座位号,并把两个剩余时段数各减 1,接下来应转到下一时段,填写:
i+=1
重新选座的分支只确定座位,没有完成当前时段的安排,所以不能在那里增加 i。
问题反馈
解析有疑问或显示异常?请先复制题目信息,再打开反馈表单填写。
题目编号:2026_05_G3_Z20_q015
