IMMC 2023中华赛A題(秋季赛)

 

官方文本pdf

2ad87f6246fe400fb355bc73f6be240a.jpeg

56bafdbc4287433bb75616a6bc8d42d5.jpeg

728c7a33a4df48d4962719609b160666.jpeg

08284e14828f4bbaa9cea7a28ebc0023.jpeg

先把问题抽象化,将各个楼命名为A1到A34,A0、A35分别为机器人A、B的充电站

对应带权无向图

b2d469e0891b486bb66abf2b49eaf8ba.png

对于对应问题,先用Dijkstra算法算各楼到图书馆的最短路径

各个楼号到图书馆的最短路径

Ai到A14距离为SAi

距离路径

A5-A14=5.2

路径为A5->A11->A17->A16->A15->A14

A11-A14=4.5

路径为A11->A17->A16->A15->A14

A4-A14=4.4

路径为A4->A3->A2->A8->A14

A35-A14=4.4

路径为A35->A29->A23->A22->A21->A15->A14

A29-A14=4.1

路径为A29->A23->A22->A21->A15->A14

A34-A14=4.1

路径为A34->A33->A32->A26->A20->A14

A3-A14=3.9

路径为A3->A2->A8->A14

A17-A14=3.9

路径为A17->A16->A15->A14

A10-A14=3.7

路径为A10->A9->A15->A14

A28-A14=3.7

路径为A28->A22->A21->A15->A14

A23-A14=3.7

路径为A23->A22->A21->A15->A14

A33-A14=3.5

路径为A33->A32->A26->A20->A14

A27-A14=3.4

路径为A27->A26->A20->A14

A22-A14=3.1

路径为A22->A21->A15->A14

A9-A14=2.9

路径为A9->A15->A14

A16-A14=2.9

路径为A16->A15->A14

A0-A14=2.9

路径为A0->A6->A12->A13->A14

A31-A14=2.9

路径为A31->A25->A19->A20->A14

A1-A14=2.8

路径为A1->A7->A13->A14

A2-A14=2.8

路径为A2->A8->A14

A30-A14=2.8

路径为A30->A24->A25->A19->A20->A14

A21-A14=2.6

路径为A21->A15->A14

A24-A14=2.3

路径为A24->A25->A19->A20->A14

A6-A14=2.2

路径为A6->A12->A13->A14

A7-A14=2.2

路径为A7->A13->A14

A15-A14=2.2

路径为A15->A14

A32-A14=2.1

路径为A32->A26->A20->A14

A18-A14=2.0

路径为A18->A12->A13->A14

A25-A14=2.0

路径为A25->A19->A20->A14

A12-A14=1.5

路径为A12->A13->A14

A19-A14=1.4

路径为A19->A20->A14

A8-A14=1.3

路径为A8->A14

A26-A14=1.3

路径为A26->A20->A14

A13-A14=1.1

路径为A13->A14

A20-A14=1.0

路径为A20->A14

问题一

首趟A、B从各自驻地出发,先到达到达图书馆,中途先收取所经楼的书本,

首趟如下图

3eff303e936b40c6956515c2c9976778.png

 

首趟A,B所用时间为回到图书馆最短路径除于对应速度

TA=SA35/speed_A=4.4/8=0.55

TB=SA0/speed_B=2.9/10=0.29

TA-TB=0.26

此时A6,A12楼的书本被B机器人回收,值为0;
A29,A23楼的书本被A机器人回收,值为0,A22被回收2本(因为容量为10本),值为5-2=3;

以B机器人首趟到达图书馆记为0时刻,而配送机器人A则会在0.26小时后出发。然后配送机器人A,B都从图书馆出发。A、B小车从图书馆出发后所用总时间设为T1,T2,(T1=T1+SAi*2/speed_A,T2=T2+SAi*2/speed_B),每趟到达图书馆后都比较T1,T2的大小,用时较少的机器人将再次出发进行下一趟的楼号遍历。直到所有的楼号遍历完毕,即所有的图书都被回收完毕。

A,B按照各个楼到图书馆的最短路径从大到小依次交替选择目标楼,返回途中进行此路径上的图书回收。(此想法可以避免:先回收图书馆附近的,导致最后回收较远楼返回时容量未满

对于返回途径的每个楼的回收书本过程:

若MAi<=C, 则MAi=0; C=C-MAi;    若该楼书本量小于等于当前容量,则被取走所有的书,该楼书本量设为0(MAi=0),当前容量则为容量减去该楼需要还的书(C=C-MAi),下次选择目标点直接跳过该点。
若MAi>C,   则MAi=MAi-C,  C=0;   若无法收取经过点的全部书本(即MAi>C),要把车容量装满(C=0),剩余书本仍存于该点中(MAi=MAi-C)。
C为0时,不用遍历该路径上剩余点,直接返回A14(图书馆),然后进入下一趟选择目标楼号。

举例演示

第一趟B车选择A5 最短路径为SA5=5.2 ,路径为A5->A11->A17->A16->A15->A14,其中MA5<C,MA5=0;C=C-MA5=4;MA11>C,MA11=MA11-C=2,C=0;C为0,剩余路径不再遍历,直接回A14;T2初始为0,T2=T2+SA5*2/speed_B=1.04h ,当前T1=0.26h  T2>T1,所以下一趟应该由A出发
第二趟A车选择A11 最短路径为4.5 ,路径为A11->A17->A16->A15->A14,其中MA11<C,MA11=0,C=C-MA11=8; MA17<C,MA17=0,C=C-MA17=6;MA16=C,MA16=0,C=C-MA16=0;C为0,剩余路径不再遍历,直接回A14;
T1初始为0.26,T1=T1+SA11*2/speed_A=1.385h ,当前T2=1.04h  T2<T1,所以下一趟应该由B出发 

第一问结果

第1趟B车选择A5,最短路径为5.2,路径为A5 -> A11 -> A17 -> A16 -> A15 -> A14
当前T1=0.260h, T2=1.040h
第2趟A车选择A11,最短路径为4.5,路径为A11 -> A17 -> A16 -> A15 -> A14
当前T1=1.385h, T2=1.040h
第3趟B车选择A4,最短路径为4.4,路径为A4 -> A3 -> A2 -> A8 -> A14
当前T1=1.385h, T2=1.920h
第4趟A车选择A34,最短路径为4.1,路径为A34 -> A33 -> A32 -> A26 -> A20 -> A14
当前T1=2.410h, T2=1.920h
第5趟B车选择A29,最短路径为4.1,路径为A29 -> A23 -> A22 -> A21 -> A15 -> A14
当前T1=2.410h, T2=2.740h
第6趟A车选择A17,最短路径为3.9,路径为A17 -> A16 -> A15 -> A14
当前T1=3.385h, T2=2.740h
第7趟B车选择A3,最短路径为3.9,路径为A3 -> A2 -> A8 -> A14
当前T1=3.385h, T2=3.520h
第8趟A车选择A10,最短路径为3.7,路径为A10 -> A9 -> A15 -> A14
当前T1=4.310h, T2=3.520h
第9趟B车选择A23,最短路径为3.7,路径为A23 -> A22 -> A21 -> A15 -> A14
当前T1=4.310h, T2=4.260h
第10趟B车选择A28,最短路径为3.7,路径为A28 -> A22 -> A21 -> A15 -> A14
当前T1=4.310h, T2=5.000h
第11趟A车选择A33,最短路径为3.5,路径为A33 -> A32 -> A26 -> A20 -> A14
当前T1=5.185h, T2=5.000h
第12趟B车选择A27,最短路径为3.4,路径为A27 -> A26 -> A20 -> A14
当前T1=5.185h, T2=5.680h
第13趟A车选择A22,最短路径为3.1,路径为A22 -> A21 -> A15 -> A14
当前T1=5.960h, T2=5.680h
第14趟B车选择A16,最短路径为2.9,路径为A16 -> A15 -> A14
当前T1=5.960h, T2=6.260h
第15趟A车选择A9,最短路径为2.9,路径为A9 -> A15 -> A14
当前T1=6.685h, T2=6.260h
第16趟B车选择A31,最短路径为2.9,路径为A31 -> A25 -> A19 -> A20 -> A14
当前T1=6.685h, T2=6.840h
第17趟A车选择A1,最短路径为2.8,路径为A1 -> A7 -> A13 -> A14
当前T1=7.385h, T2=6.840h
第18趟B车选择A30,最短路径为2.8,路径为A30 -> A24 -> A25 -> A19 -> A20 -> A14
当前T1=7.385h, T2=7.400h
第19趟A车选择A2,最短路径为2.8,路径为A2 -> A8 -> A14
当前T1=8.085h, T2=7.400h
第20趟B车选择A21,最短路径为2.6,路径为A21 -> A15 -> A14
当前T1=8.085h, T2=7.920h
第21趟B车选择A24,最短路径为2.3,路径为A24 -> A25 -> A19 -> A20 -> A14
当前T1=8.085h, T2=8.380h
第22趟A车选择A7,最短路径为2.2,路径为A7 -> A13 -> A14
当前T1=8.635h, T2=8.380h
第23趟B车选择A15,最短路径为2.2,路径为A15 -> A14
当前T1=8.635h, T2=8.820h
第24趟A车选择A6,最短路径为2.2,路径为A6 -> A12 -> A13 -> A14
当前T1=9.185h, T2=8.820h
第25趟B车选择A32,最短路径为2.1,路径为A32 -> A26 -> A20 -> A14
当前T1=9.185h, T2=9.240h
第26趟A车选择A18,最短路径为2.0,路径为A18 -> A12 -> A13 -> A14
当前T1=9.685h, T2=9.240h

分别用时:A机器人10.525小时, B机器人9.820小时
任务完成!总用时:10.525小时

问题二

对于该问题,问题一思路仍然适用,每个楼都有经过,只需在去的时候带上需要借的书即可

其中从驻地到图书馆最短路径上的书,在最后一趟返回驻地充电时,带上需要充的点即可

3f9ced17e4ee47ca81ef40ae52f7f4ce.png

即B返回驻地途中,A12借3本,A6借2本

问题二结果

第1趟B车选择A5,最短路径为5.2,路径为A5 -> A11 -> A17 -> A16 -> A15 -> A14
第2趟A车选择A11,最短路径为4.5,路径为A11 -> A17 -> A16 -> A15 -> A14
第3趟B车选择A4,最短路径为4.4,路径为A4 -> A3 -> A2 -> A8 -> A14
A2借了1本书
A4借了2本书

第4趟A车选择A34,最短路径为4.1,路径为A34 -> A33 -> A32 -> A26 -> A20 -> A14
A20借了3本书
A32借了2本书

第5趟B车选择A29,最短路径为4.1,路径为A29 -> A23 -> A22 -> A21 -> A15 -> A14
第6趟A车选择A17,最短路径为3.9,路径为A17 -> A16 -> A15 -> A14
第7趟B车选择A3,最短路径为3.9,路径为A3 -> A2 -> A8 -> A14
第8趟A车选择A10,最短路径为3.7,路径为A10 -> A9 -> A15 -> A14
A10借了1本书
第9趟B车选择A23,最短路径为3.7,路径为A23 -> A22 -> A21 -> A15 -> A14
第10趟B车选择A28,最短路径为3.7,路径为A28 -> A22 -> A21 -> A15 -> A14
A28借了2本书
第11趟A车选择A33,最短路径为3.5,路径为A33 -> A32 -> A26 -> A20 -> A14
第12趟B车选择A27,最短路径为3.4,路径为A27 -> A26 -> A20 -> A14
第13趟A车选择A22,最短路径为3.1,路径为A22 -> A21 -> A15 -> A14
第14趟B车选择A16,最短路径为2.9,路径为A16 -> A15 -> A14
第15趟A车选择A9,最短路径为2.9,路径为A9 -> A15 -> A14
第16趟B车选择A31,最短路径为2.9,路径为A31 -> A25 -> A19 -> A20 -> A14
第17趟A车选择A1,最短路径为2.8,路径为A1 -> A7 -> A13 -> A14
第18趟B车选择A30,最短路径为2.8,路径为A30 -> A24 -> A25 -> A19 -> A20 -> A14
A24借了2本书
第19趟A车选择A2,最短路径为2.8,路径为A2 -> A8 -> A14
第20趟B车选择A21,最短路径为2.6,路径为A21 -> A15 -> A14
第21趟B车选择A24,最短路径为2.3,路径为A24 -> A25 -> A19 -> A20 -> A14
第22趟A车选择A7,最短路径为2.2,路径为A7 -> A13 -> A14
第23趟B车选择A15,最短路径为2.2,路径为A15 -> A14
第24趟A车选择A6,最短路径为2.2,路径为A6 -> A12 -> A13 -> A14
第25趟B车选择A32,最短路径为2.1,路径为A32 -> A26 -> A20 -> A14
第26趟A车选择A18,最短路径为2.0,路径为A18 -> A12 -> A13 -> A14
A18借了2本书

分别用时:A机器人10.525小时, B机器人9.820小时
任务完成!总用时:10.525小时

对应代码

图像生成代码

import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import networkx as nx
# 设置中文字体,防止中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
# 创建图
G = nx.Graph()
# 添加边和权重
edges_with_weights = [
    ('A0', 'A1', 0.6), ('A1', 'A2', 0.3), ('A2', 'A3', 1.1), ('A3', 'A4', 0.5), ('A4', 'A5', 0.8),
    ('A6', 'A7', 0.5), ('A7', 'A8', 1.2), ('A8', 'A9', 1.8), ('A9', 'A10', 0.8), ('A10', 'A11', 1.0),
    ('A12', 'A13', 0.4), ('A13', 'A14', 1.1), ('A14', 'A15', 2.2), ('A15', 'A16', 0.7), ('A16', 'A17', 1.0),
    ('A18', 'A19', 0.9), ('A19', 'A20', 0.4),## (A20, A21, 不通湖泊)
    ('A21', 'A22', 0.5), ('A22', 'A23', 0.6),
    ('A24', 'A25', 0.3), ('A25', 'A26', 1.1), ('A26', 'A27', 2.1), ('A27', 'A28', 0.8), ('A28', 'A29', 1.1),
    ('A30', 'A31', 0.4), ('A31', 'A32', 0.9), ('A32', 'A33', 1.4), ('A33', 'A34', 0.6), ('A34', 'A35', 0.5),
    ('A0', 'A6', 0.7), ('A1', 'A7', 0.6), ('A2', 'A8', 1.5), ('A3', 'A9', 1.7), ('A4', 'A10', 2.0), ('A5', 'A11', 0.7),
    ('A6', 'A12', 0.7), ('A7', 'A13', 1.1), ('A8', 'A14', 1.3), ('A9', 'A15', 0.7), ('A10', 'A16', 1.0), ('A11', 'A17', 0.6),
    ('A12', 'A18', 0.5), ('A13', 'A19', 0.7), ('A14', 'A20', 1.0), ('A15', 'A21', 0.4), ('A16', 'A22', 0.5), ('A17', 'A23', 0.6),
    ('A18', 'A24', 1.1), ('A19', 'A25', 0.6), ('A20', 'A26', 0.3), ('A21', 'A27', 0.8), ('A22', 'A28', 0.6), ('A23', 'A29', 0.4),
    ('A24', 'A30', 0.5), ('A25', 'A31', 0.9), ('A26', 'A32', 0.8), ('A27', 'A33', 0.7), ('A28', 'A34', 0.5), ('A29', 'A35', 0.3)
]

G.add_weighted_edges_from(edges_with_weights)

# 按楼号优先纵行排列的节点位置
rows = 6  # 每行的节点数
pos = {f'A{i}': (i // rows, -(i % rows)) for i in range(36)}

# ...之前的代码...

# 设置节点标签,即楼号和楼名的组合
labels = {
    'A0': 'A0 充电站robotB',
    'A1': 'A1 四美楼',
    'A2': 'A2 芳邻楼',
    'A3': 'A3 凌云楼',
    'A4': 'A4 远山楼',
    'A5': 'A5 重霄楼',
    'A6': 'A6 北辰楼',
    'A7': 'A7 弥津楼',
    'A8': 'A8 映雪楼',
    'A9': 'A9 高洁楼',
    'A10': 'A10 南溟楼',
    'A11': 'A11 长洲楼',
    'A12': 'A12 秋水楼',
    'A13': 'A13 空地1',
    'A14': 'A14 图书馆',
    'A15': 'A15 临川楼',
    'A16': 'A16 景明楼',
    'A17': 'A17 清风楼',
    'A18': 'A18 皓月楼',
    'A19': 'A19 耸翠楼',
    'A20': 'A20 朱华楼',
    'A21': 'A21 空地2',
    'A22': 'A22 绿竹楼',
    'A23': 'A23 沉璧楼',
    'A24': 'A24 雅望楼',
    'A25': 'A25 朝晖楼',
    'A26': 'A26 流丹楼',
    'A27': 'A27 俊采楼',
    'A28': 'A28 汀兰楼',
    'A29': 'A29 兰亭楼',
    'A30': 'A30 郁青楼',
    'A31': 'A31 星耀楼',
    'A32': 'A32 万千楼',
    'A33': 'A33 东隅楼',
    'A34': 'A34 长风楼',
    'A35': 'A35 充电站robotA'
}
# 绘制图
plt.figure(figsize=(12, 8))
nx.draw(G, pos, labels=labels, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_family='SimHei')
# 添加边的权重标签
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8, font_family='SimHei')
plt.title("加权无向图")  # 标题也使用中文
plt.axis('off')
plt.tight_layout()
plt.savefig('学校各建筑与交通路线示意图.png')
plt.show()

各个楼号到图书馆的最短路径Dijkstra

#按最小路径 从高到低排序
import heapq
# 距离图
distances = {
    ('A0', 'A1'): 0.6, ('A1', 'A2'): 0.3, ('A2', 'A3'): 1.1, ('A3', 'A4'): 0.5,
    ('A4', 'A5'): 0.8, ('A6', 'A7'): 0.5, ('A7', 'A8'): 1.2, ('A8', 'A9'): 1.8,
    ('A9', 'A10'): 0.8, ('A10', 'A11'): 1.0, ('A12', 'A13'): 0.4, ('A13', 'A14'): 1.1,
    ('A14', 'A15'): 2.2, ('A15', 'A16'): 0.7, ('A16', 'A17'): 1.0, ('A18', 'A19'): 0.9,
    ('A19', 'A20'): 0.4, ('A20', 'A21'): 100, ('A21', 'A22'): 0.5, ('A22', 'A23'): 0.6,
    ('A24', 'A25'): 0.3, ('A25', 'A26'): 1.1, ('A26', 'A27'): 2.1, ('A27', 'A28'): 0.8,
    ('A28', 'A29'): 1.1, ('A30', 'A31'): 0.4, ('A31', 'A32'): 0.9, ('A32', 'A33'): 1.4,
    ('A33', 'A34'): 0.6, ('A34', 'A35'): 0.5, ('A0', 'A6'): 0.7, ('A1', 'A7'): 0.6,
    ('A2', 'A8'): 1.5, ('A3', 'A9'): 1.7, ('A4', 'A10'): 2.0, ('A5', 'A11'): 0.7,
    ('A6', 'A12'): 0.7, ('A7', 'A13'): 1.1, ('A8', 'A14'): 1.3, ('A9', 'A15'): 0.7,
    ('A10', 'A16'): 1.0, ('A11', 'A17'): 0.6, ('A12', 'A18'): 0.5, ('A13', 'A19'): 0.7,
    ('A14', 'A20'): 1.0, ('A15', 'A21'): 0.4, ('A16', 'A22'): 0.5, ('A17', 'A23'): 0.6,
    ('A18', 'A24'): 1.1, ('A19', 'A25'): 0.6, ('A20', 'A26'): 0.3, ('A21', 'A27'): 0.8,
    ('A22', 'A28'): 0.6, ('A23', 'A29'): 0.4, ('A24', 'A30'): 0.5, ('A25', 'A31'): 0.9,
    ('A26', 'A32'): 0.8, ('A27', 'A33'): 0.7, ('A28', 'A34'): 0.5, ('A29', 'A35'): 0.3
}

# 所有节点
nodes = set()
for (start, end) in distances.keys():
    nodes.add(start)
    nodes.add(end)

# 创建邻接表
graph = {node: {} for node in nodes}
for (start, end), dist in distances.items():
    graph[start][end] = dist
    graph[end][start] = dist


def dijkstra(source, target):
    dist = {node: float('inf') for node in nodes}
    dist[source] = 0
    priority_queue = [(0, source)]
    path = {node: [] for node in nodes}

    while priority_queue:
        current_dist, current_node = heapq.heappop(priority_queue)

        if current_dist > dist[current_node]:
            continue

        for neighbor, weight in graph[current_node].items():
            distance = current_dist + weight

            if distance < dist[neighbor]:
                dist[neighbor] = distance
                path[neighbor] = path[current_node] + [current_node]
                heapq.heappush(priority_queue, (distance, neighbor))

    return dist[target], path[target] + [target]


# 计算每个节点到A14的最短路径
shortest_paths = {}
for node in nodes:
    if node != 'A14':
        shortest_distance, shortest_path = dijkstra(node, 'A14')
        shortest_paths[node] = (shortest_distance, shortest_path)

# 按路径从高到低排序
sorted_paths = dict(sorted(shortest_paths.items(), key=lambda item: item[1][0], reverse=True))

# 输出结果
for node, (distance, path) in sorted_paths.items():
    print(f'{node}-A14={distance:.1f}, 路径为{"->".join(path)}')
    # print(f'{node}最短路径为:{distance:.1f}')

问题一


#第一题
# 初始化数据
Return_book = {   #还书量
    'A1': 3, 'A2': 4, 'A3': 2, 'A4': 5, 'A5': 6, 'A6': 6, 'A7': 5, 'A8': 2, 'A9': 4, 'A10': 3,
    'A11': 6, 'A12': 4, 'A13': 0, 'A14': 0, 'A15': 3, 'A16': 6, 'A17': 2, 'A18': 7, 'A19': 4, 'A20': 2,
    'A21': 0, 'A22': 3, #A22被A车拿走两本 A22=5-2=3
    'A23': 6, 'A24': 5, 'A25': 3, 'A26': 8, 'A27': 3, 'A28': 6, 'A29': 2, 'A30': 3,
    'A31': 4, 'A32': 2, 'A33': 1, 'A34': 5
}
Borrow_books = {  #借书
    'A2': 1,'A4': 2,'A10': 1,'A18': 2,'A20': 3,'A24': 2,'A28': 2,'A32': 2
}

distances_and_paths = {
    'A5': (5.2, ['A5', 'A11', 'A17', 'A16', 'A15', 'A14']),
    'A11': (4.5, ['A11', 'A17', 'A16', 'A15', 'A14']),
    'A4': (4.4, ['A4', 'A3', 'A2', 'A8', 'A14']),
    'A34': (4.1, ['A34', 'A33', 'A32', 'A26', 'A20', 'A14']),
    'A29': (4.1, ['A29', 'A23', 'A22', 'A21', 'A15', 'A14']),
    'A17': (3.9, ['A17', 'A16', 'A15', 'A14']),
    'A3': (3.9, ['A3', 'A2', 'A8', 'A14']),
    'A10': (3.7, ['A10', 'A9', 'A15', 'A14']),
    'A23': (3.7, ['A23', 'A22', 'A21', 'A15', 'A14']),
    'A28': (3.7, ['A28', 'A22', 'A21', 'A15', 'A14']),
    'A33': (3.5, ['A33', 'A32', 'A26', 'A20', 'A14']),
    'A27': (3.4, ['A27', 'A26', 'A20', 'A14']),
    'A22': (3.1, ['A22', 'A21', 'A15', 'A14']),
    'A16': (2.9, ['A16', 'A15', 'A14']),
    'A9': (2.9, ['A9', 'A15', 'A14']),
    'A31': (2.9, ['A31', 'A25', 'A19', 'A20', 'A14']),
    'A1': (2.8, ['A1', 'A7', 'A13', 'A14']),
    'A30': (2.8, ['A30', 'A24', 'A25', 'A19', 'A20', 'A14']),
    'A2': (2.8, ['A2', 'A8', 'A14']),
    'A21': (2.6, ['A21', 'A15', 'A14']),
    'A24': (2.3, ['A24', 'A25', 'A19', 'A20', 'A14']),
    'A7': (2.2, ['A7', 'A13', 'A14']),
    'A15': (2.2, ['A15', 'A14']),
    'A6': (2.2, ['A6', 'A12', 'A13', 'A14']),
    'A32': (2.1, ['A32', 'A26', 'A20', 'A14']),
    'A18': (2.0, ['A18', 'A12', 'A13', 'A14']),
    'A25': (2.0, ['A25', 'A19', 'A20', 'A14']),
    'A12': (1.5, ['A12', 'A13', 'A14']),
    'A19': (1.4, ['A19', 'A20', 'A14']),
    'A26': (1.3, ['A26', 'A20', 'A14']),
    'A8': (1.3, ['A8', 'A14']),
    'A13': (1.1, ['A13', 'A14']),
    'A20': (1.0, ['A20', 'A14'])
}

speed_A, speed_B = 8, 10
T1, T2 = 0.26, 0

def collect_books(car, target):
    global Return_book, T1, T2
    C = 10
    distance, path = distances_and_paths[target]

    print(f"第{trip}趟{car}车选择{target},最短路径为{distance},路径为{' -> '.join(path)}")

    for point in path[:-1]:  # 不包括A14
        if C == 0:
            break
        if Return_book[point] <= C:
            C -= Return_book[point]
            # print(f"{point}书本量{Return_book[point]}小于等于当前容量{C+Return_book[point]},被取走所有的书")
            Return_book[point] = 0
        else:
            # print(f"{point}书本量{Return_book[point]}大于当前容量{C},取走{C}本书")
            Return_book[point] -= C
            C = 0

    if car == 'A':
        T1 += distance * 2 / speed_A
    else:
        T2 += distance * 2 / speed_B
    print(f"当前T1={T1:.3f}h, T2={T2:.3f}h")      #当前时间

# 主循环
trip = 1
for target in distances_and_paths.keys():
    if T1 <= T2:
        car = 'A'
    else:
        car = 'B'

    collect_books(car, target)
    print()
    trip += 1

    if sum(Return_book.values()) == 0:
        break
T1+=0.29+0.55;   #把B机器人到达图书馆记为0时刻
T2+=0.29*2;
print(f"分别用时:A机器人{T1:.3f}小时, B机器人{T2:.3f}小时")
print(f"任务完成!总用时:{max(T1, T2):.3f}小时")

问题二

#第二题
# 初始化数据
Return_book = {   #还书量
    'A1': 3, 'A2': 4, 'A3': 2, 'A4': 5, 'A5': 6, 'A6': 6, 'A7': 5, 'A8': 2, 'A9': 4, 'A10': 3,
    'A11': 6, 'A12': 4, 'A13': 0, 'A14': 0, 'A15': 3, 'A16': 6, 'A17': 2, 'A18': 7, 'A19': 4, 'A20': 2,
    'A21': 0, 'A22': 3, #A22被A车拿走两本 A22=5-2=3
    'A23': 6, 'A24': 5, 'A25': 3, 'A26': 8, 'A27': 3, 'A28': 6, 'A29': 2, 'A30': 3,
    'A31': 4, 'A32': 2, 'A33': 1, 'A34': 5
}
Borrow_books = {  #借书
    'A2': 1,'A4': 2,'A10': 1,'A18': 2,'A20': 3,'A24': 2,'A28': 2,'A32': 2
}

distances_and_paths = {
    'A5': (5.2, ['A5', 'A11', 'A17', 'A16', 'A15', 'A14']),
    'A11': (4.5, ['A11', 'A17', 'A16', 'A15', 'A14']),
    'A4': (4.4, ['A4', 'A3', 'A2', 'A8', 'A14']),
    'A34': (4.1, ['A34', 'A33', 'A32', 'A26', 'A20', 'A14']),
    'A29': (4.1, ['A29', 'A23', 'A22', 'A21', 'A15', 'A14']),
    'A17': (3.9, ['A17', 'A16', 'A15', 'A14']),
    'A3': (3.9, ['A3', 'A2', 'A8', 'A14']),
    'A10': (3.7, ['A10', 'A9', 'A15', 'A14']),
    'A23': (3.7, ['A23', 'A22', 'A21', 'A15', 'A14']),
    'A28': (3.7, ['A28', 'A22', 'A21', 'A15', 'A14']),
    'A33': (3.5, ['A33', 'A32', 'A26', 'A20', 'A14']),
    'A27': (3.4, ['A27', 'A26', 'A20', 'A14']),
    'A22': (3.1, ['A22', 'A21', 'A15', 'A14']),
    'A16': (2.9, ['A16', 'A15', 'A14']),
    'A9': (2.9, ['A9', 'A15', 'A14']),
    'A31': (2.9, ['A31', 'A25', 'A19', 'A20', 'A14']),
    'A1': (2.8, ['A1', 'A7', 'A13', 'A14']),
    'A30': (2.8, ['A30', 'A24', 'A25', 'A19', 'A20', 'A14']),
    'A2': (2.8, ['A2', 'A8', 'A14']),
    'A21': (2.6, ['A21', 'A15', 'A14']),
    'A24': (2.3, ['A24', 'A25', 'A19', 'A20', 'A14']),
    'A7': (2.2, ['A7', 'A13', 'A14']),
    'A15': (2.2, ['A15', 'A14']),
    'A6': (2.2, ['A6', 'A12', 'A13', 'A14']),
    'A32': (2.1, ['A32', 'A26', 'A20', 'A14']),
    'A18': (2.0, ['A18', 'A12', 'A13', 'A14']),
    'A25': (2.0, ['A25', 'A19', 'A20', 'A14']),
    'A12': (1.5, ['A12', 'A13', 'A14']),
    'A19': (1.4, ['A19', 'A20', 'A14']),
    'A26': (1.3, ['A26', 'A20', 'A14']),
    'A8': (1.3, ['A8', 'A14']),
    'A13': (1.1, ['A13', 'A14']),
    'A20': (1.0, ['A20', 'A14'])
}

speed_A, speed_B = 8, 10
T1, T2 = 0.26, 0

# 定义一个全局集合,用于跟踪已经输出过的借书点
outputted_borrowed_points = set()

def collect_books(car, target):
    global Return_book, T1, T2, Borrow_books, outputted_borrowed_points
    C = 10
    distance, path = distances_and_paths[target]
    borrowed_points = []  # 存储借书的点和数量

    print(f"第{trip}趟{car}车选择{target},最短路径为{distance},路径为{' -> '.join(path)}")

    # 收集书本
    for point in path[:-1]:  # 不包括A14
        if C == 0:
            break
        if point in Borrow_books:  # 如果当前点有借书记录
            if point not in outputted_borrowed_points:  # 检查是否已经输出过
                borrowed_points.append((point, Borrow_books[point]))  # 记录借书点和数量
                outputted_borrowed_points.add(point)  # 标记为已输出

        if Return_book[point] <= C:
            C -= Return_book[point]
            Return_book[point] = 0
            # print(f"{point}书本量{Return_book[point]}小于等于当前容量{C},被取走所有的书")
        else:
            C -= Return_book[point]
            # print(f"{point}书本量{Return_book[point]}大于当前容量{C},取走{Return_book[point]}本书")
            Return_book[point] = C

    # 逆序输出借书的点和数量
    if borrowed_points:
        for point, quantity in reversed(borrowed_points):  # 使用 reversed 函数逆序输出
            print(f"{point}借了{quantity}本书")

    if car == 'A':
        T1 += distance * 2 / speed_A
    else:
        T2 += distance * 2 / speed_B
    # print(f"当前T1={T1:.3f}h, T2={T2:.3f}h")  # 当前时间

# 主循环
trip = 1
for target in distances_and_paths.keys():
    if T1 <= T2:
        car = 'A'
    else:
        car = 'B'

    collect_books(car, target)
    print()
    trip += 1

    if sum(Return_book.values()) == 0:
        break

T1 += 0.29 + 0.55  # 把B机器人到达图书馆记为0时刻
T2 += 0.29 * 2
print(f"分别用时:A机器人{T1:.3f}小时, B机器人{T2:.3f}小时")
print(f"任务完成!总用时:{max(T1, T2):.3f}小时")

 

 

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值