有k个节点的转发队列,每个节点转发能力为m,缓存能力n(表示此节点可立即转发m个包,剩余的缓存,最多缓存n个包再剩余的丢弃,缓存的包在下轮继续转发)。另外,此队列中某些节点可能因故障需要直接跳过转发,但不会有两个连续故障的节点。
现分两轮操作,第一轮向此队列发送a个数据包让其转发第二轮,直接驱动让缓存的数据包继续转发。
求两轮最后可能收到的最少数据包总个数(如果第二轮缓存仍有数据包,缓存包按丢弃处理)
1<=k<=40
1<=m,n<=1000
1<=a<=1000
例如:有两个节点,节点1(转发能力m:50,缓存能力n:60)和节点2(m:30,n:25),发送包数为120。
# -*- coding: utf-8 -*-
import numpy as np
num_k = int(input("节点数k:"))
m_n = input("节点转发数m,缓存数n:")
m_n_list = m_n.split(' ') #各节点参数拆分
m = np.zeros(num_k,dtype=np.int)
n = np.zeros(num_k,dtype=np.int)
for i in range(num_k):
temp = m_n_list[i].split(',') #各节点m,n拆分
m[i] = int(temp[0])
n[i] = int(temp[1])
tm = m.copy() #中间变量存储,必须用copy,否则则会出现同步变化的故障
tn = n.copy()
a = int(input("接收数:"))
def f(m, n):
# 第一轮
rec_num1 = a; #第一轮外部接收
send_m = np.zeros(num_k,dtype=int)
res_n = np.zeros(num_k,dtype=int)
for i in range(num_k):
if m[i] == 0: continue #故障节点直接跳过
if rec_num1 > m[i]: #接收大于转发
temp = rec_num1 - m[i] #节点剩余数
send_m[i] = m[i] #节点发送数
if temp > n[i]:
res_n[i] = n[i] #超缓存,节点缓存数
else:
res_n[i] = temp #不超缓存,节点缓存数
else: #接收小于转发
send_m[i] = rec_num1 #节点发送数
rec_num1 = send_m[i] #下节点接收数,最终节点发送数
# 第二轮
rec_num2 = 0 #第二轮外部接收
for i in range(num_k):
if m[i] == 0: continue #故障节点直接跳过
rec_num2 = res_n[i] + rec_num2 #缓存加接收
if rec_num2 > m[i]: #接收大于转发
temp = rec_num2 - m[i] #节点剩余数
send_m[i] = m[i] #节点发送数
if temp > n[i]:
res_n[i] = n[i] #超缓存,节点缓存数
else:
res_n[i] = temp #不超缓存,节点缓存数
else: #接收小于转发
send_m[i] = rec_num2 #节点发送数
rec_num2 = send_m[i] #下节点接收数,最终节点发送数
send_total = rec_num1 + rec_num2 #两轮最后节点发送总数
return send_total
# 生成最大故障
for i in range(num_k): #生成最大故障节点组,此时转发最少
if i % 2 == 0: # 偶数故障
m[i] = 0
n[i] = 0
min_even = f(m,n)
m = tm.copy()
n = tn.copy()
for i in range(num_k): #生成最大故障节点组,此时转发最少
if (i+1) % 2 == 0: # 奇数故障,必须加括号
m[i] = 0
n[i] = 0
min_odd = f(m,n)
if min_even > min_odd:
print("最少收包数:",min_odd)
else:
print("最少收包数:",min_even)