2019美赛D题人员疏散模拟(错误解答,仅记录)
2021年3月21号编辑内容
特此说明:笔主写这篇文章的时候还是大三上学期结束,认知、技术都完全不过关,此时再回看这篇文章,着实有很多问题,甚至是误导。特此说明
笔主从学习Python,也就是写下这篇文章的时期,目前从事前端开发工作,也开始学习C++,也没有那种机会进入相关算法研发工作。今时看来,此文的编码、思想都略显幼稚甚至荒唐。
毕竟是自己踩下的脚印,不忍抹去,此段话放在开头,希望刷到的同学谨慎参考,谢谢各位。
———————————————————————————————————————————
有幸参加了2019年美国大学生数学建模比赛。比赛过程中担任的角色中有编程任务,现将当时的代码和大家分享。比赛结束后抽空将代码完善了一下,仍然有诸多不足之处。
一、我们团队的想法
我们团队怎么也找不到卢浮宫的建筑平面图,有找到的吗????不能精确定位模拟,所以就基于疏散问题建立了自己的平面图。
1、假设(部分)
(1)场馆内无障碍物(这样简化了很多)
(2)场馆内人员单位时间内最多能移动一个元胞距离(很关键,不然非常)
2、馆内人员移动分析
即单位时间内可以移动八个方向,每次一个元胞距离
3、安全出口数量以及安全出口的考虑
如果考虑多个安全出口,仅仅比赛那点时间,我这点水平编程是不够的,所以指定只有一个安全出口;在考虑安全出口位置的时候,我们也指定出口位置为墙上的一个开口,比赛结束后,我将代码优化补全,现在支持安全出口的位置在室内任何地方。
二、代码部分
因为不是一篇写这次比赛解决方法的博客,下面我重点展示代码实现。先展示各个点的实现,最后在附送上完整代码。
运用到matplotlib库进行可视化,所以就不提基础部分,主要展示怎么将现实问题抽象成代码
1、创建房间、创建人员及初始位置生成、安全出口
N, row, column = 250, 20, 20 #室内人数,矩阵的行数,矩阵的列数
room = np.zeros((row + 2, column + 2)) # 创建房间
export = [(6, 11, 'E')] # 设定出口位置和开门方向,此处为坐标轴坐标
** 注意:**出口的坐标表示为二维直角坐标系的定位方式,并非出口在矩阵中的索引,出口方向分别为‘N’‘S’‘W’‘E’,对应四个方位。
def initial_room():
'''
生成初始人员并进行随机分配
'''
coordinates = [] # 室内人员坐标
for i in range(N):
generated_data = [random.randint(1, row), random.randint(1, column)]
if not generated_data in coordinates: # 去掉重复数据
coordinates.append(generated_data)
for i in range(len(coordinates)):
room[coordinates[i][0]][coordinates[i][1]] = 1
# 创建围墙、创建出口
for i in range(len(room)):
for j in range(len(room)):
if i == 0 or i == len(room) - 1 or j == 0 or j == len(room[i]) - 1:
room[i][j] = 9
for i in range(len(export)):
room[export[i][1]][export[i][0]] = 8
return
人员随机分配,对应矩阵中的索引,设置删除重复的位置,即得一个人对应一个位置。围墙使用数值9表示,出口使用数值8表示。
2、可视化
for i in range(1, len(room) - 1):
for j in range(1, len(room[i]) - 1):
if room[i][j] == 1:
rect = mpathes.Circle((j + 0.5, i + 0.5), 0.3, color='grey')
ax.add_patch(rect)
plt.show()
将矩阵索引与二维坐标Y轴一一对应,即矩阵索引为0的列表对应坐标轴Y方向最小的坐标,便于后续编程
完整代码
代码半完整写下来将近300行,还有一些没有完善,下文会提到
import matplotlib.pyplot as plt
import matplotlib.patches as mpathes
import numpy as np
import random
# 初始位置生成
def initial_room():
'''
生成初始人员并进行随机分配
'''
coordinates = [] # 室内人员坐标
for i in range(N):
generated_data = [random.randint(1, row), random.randint(1, column)]
if not generated_data in coordinates: # 去掉重复数据
coordinates.append(generated_data)
for i in range(len(coordinates)):
room[coordinates[i][0]][coordinates[i][1]] = 1
# 创建围墙、创建出口
for i in range(len(room)):
for j in range(len(room)):
if i == 0 or i == len(room) - 1 or j == 0 or j == len(room[i]) - 1:
room[i][j] = 9
for i in range(len(export)):
room[export[i][1]][export[i][0]] = 8
return
# 创建平台
def create_flat():
# fig, ax = plt.subplots()
plt.xticks(np.arange(0, column + 3, 1.0))
plt.yticks(np.arange(0, row + 3, 1.0))
plt.grid(linestyle='--')
wall_botton = mpathes.Rectangle((0, 0), column + 2, 1, color='grey')
wall_left = mpathes.Rectangle((0, 0), 1, row + 2, color='grey')
wall_top = mpathes.Rectangle((0, row + 1), column + 2, 1, color='grey')
wall_right = mpathes.Rectangle((column + 1, 0), 1