第 15 题
答案与解析
第(1)小题
2,4,0,2
计划采购量需扣除后续被替换及期末退还的材料。每天生产后临时库存保持8个单位;遇到更低价格时,退还较贵库存,并从原采购日的计划量中扣除。
| 日期、单价 | 当天模拟处理 | 当天生产后临时库存 | 各日累计净采购量 |
|---|---|---|---|
| 第1天,6元 | 临时采购10个,消耗2个 | 第1天材料8个 | 10,0,0,0 |
| 第2天,4元 | 替换第1天库存8个,扣减第1天采购量;采购10个,消耗2个 | 第2天材料8个 | 2,10,0,0 |
| 第3天,5元 | 优先消耗较便宜的第2天材料2个,再采购2个补充库存 | 第2天材料6个,第3天材料2个 | 2,10,2,0 |
| 第4天,3元 | 替换现有库存8个,分别扣减第2天6个、第3天2个;采购10个,消耗2个 | 第4天材料8个 | 2,4,0,10 |
| 期末退还 | 退还第4天剩余的8个 | 空 | 2,4,0,2 |
第(2)①小题
1
程序分析
y = x
while head != -1 and a[head][1] <= y:
y -= a[head][1]
head = a[head][2]
a[head][1] -= y
return head题干规定每个结点依次保存采购日、剩余数量和后继下标,-1表示链尾。head是头指针,保存首结点下标;有效链按单价升序排列,从首结点开始消耗可优先使用便宜材料。
y初值为x。首结点剩余量不大于y时,将该批数量从y中扣除,再把head移到后继,继续处理尚未满足的消耗量。因此y记录本次还需消耗的数量,用完的结点随head后移而退出有效链。
循环结束且head有效时,首结点剩余量大于y,从中扣除y后返回head。第(3)问调用前库存为v+x,消耗x后仍剩v,可保证此时head有效。
head=1,有效链的结点下标为1→2,结点0不在其中。y初值为1,首结点剩余量a[1][1]=5,5≤1不成立,循环不执行。随后将该结点剩余量减为4,head未改变,返回1。
第(2)②小题
错
共用程序分析见第(2)①小题。
每个结点的三个数据项下标为0、1、2,执行a[head][3]会越界,但该语句位于while循环体内。
以①的数据测试时,首结点剩余5个单位,本次只需消耗1个单位,5≤1不成立,循环体不执行,因而不会触发这处下标越界。
第(3)小题
p != -1 and price[a[p][0]] <= price[i]
rep += a[p][1]
head = len(a)-1
程序分析
buy = [0]*len(price)
a = [[0,v,-1]]
head,buy[0] = 0,v
for i in range(1,len(price)):
...题干规定a的每个结点保存采购日、剩余数量和后继下标,head为头指针。采购日是price中的下标,用于取得该批材料的单价。
初始结点[0,v,-1]对应price[0]=1000,数量为v,是高于所有实际单价的虚拟库存。外层循环按日期依次处理采购计划。
rep = 0
q,p = -1,head
while ①:
q = p
p = a[p][2]p从head开始。每轮先执行q=p,再用a[p][2]移到后继,所以q始终记录刚越过的结点下标,p指向下一待检查结点。若尚未越过任何结点,q=-1;越过链尾后,p=-1。
while p != -1:
②
buy[a[p][0]] -= a[p][1]
p = a[p][2]从查找停止处继续遍历到链尾。a[p][0]是当前批次的采购日,a[p][1]是剩余量;将剩余量从buy对应日期的记录中扣除,正是在撤销这批尚未消耗材料的采购计划。
a.append([i,rep+x,-1]) # 为a追加一个元素
buy[i] = rep+x建立当天的新结点[i,rep+x,-1],追加到数组末尾,并将rep+x记入当天计划采购量buy[i]。新结点下标为len(a)-1,尚需接入有效链。
if q != -1:
a[q][2] = len(a)-1
else:
③q有效时,把其后继改为新结点,保留查找阶段越过的结点,断开其后已退还的库存。被断开的旧结点仍在数组中,但不再属于有效库存;q=-1时需由else分支处理。
head = use(a,head,x)调用use从首结点开始消耗x个单位,返回剩余库存的头指针。为优先使用便宜材料,前面的查找和接链需保持有效链按单价非降序排列。
# 退还仓库里剩余的材料,代码略
total = 0
for i in range(1,len(price)):
total += buy[i]*price[i]
print("第"+str(i)+"天的采购量为:",buy[i])
print("采购的最小费用为",total)退还期末剩余库存后,buy[i]是第i天最终净采购量。累加buy[i]×price[i]得到总费用,统计从第1天开始,不计第0天虚拟库存。
填空分析
①
后续循环退还从p开始的库存,因此应先越过单价不高于当天价格的结点,在第一个更贵的结点处停止。原链按单价非降序排列,保留部分接上当天的新结点后仍保持有序。
p是结点在a中的下标,a[p][0]是该批材料的采购日,其单价为price[a[p][0]]。先判断p!=-1,确认结点有效后再比较单价,填写:
p != -1 and price[a[p][0]] <= price[i]
②
新购量rep+x中,x用于补充当天消耗,rep应补回被退还的库存。因此每访问一个待退还结点,就把剩余量a[p][1]累加到rep,填写:
rep += a[p][1]
当天开始有v个单位,退还rep后剩v-rep;购入rep+x,再消耗x,生产后库存仍为v。
③
q=-1说明没有保留任何旧结点。新结点已追加到数组末尾,应使head保存它的下标,让后续use从新库存开始消耗,填写:
head = len(a)-1
问题反馈
解析有疑问或显示异常?请先复制题目信息,再打开反馈表单填写。
题目编号:2026_04_G3_taizhouermo_q015
