1.问题定义
a.能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
b.为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)
c.赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。
2、问题分析
在a中首先我们可以用了哈希表的查找方式。std::map<std::string, std::vector<Team>>来创建一个映射,将参赛学校名称与团队向量关联起来。
在遍历给定的团队列表时,通过检查团队的学校是否与输入的学校名称匹配,将符合条件的团队添加到相应赛事类别的团队向量中。这里通过使用schoolTeams[team.eventCategory].push_back(team)将符合条件的团队添加到schoolTeams映射中。
最后,代码根据schoolTeams映射是否为空来判断是否找到符合条件的团队。如果映射为空,则输出"未找到该学校参赛的团队!"的提示信息。否则,遍历按赛事类别分组的团队信息,输出参赛团队的基本信息。
关于b,
需要考虑使用多种元素进行实现:
- 每个参赛队需要被量化并装配到所属赛事类别的队列中。
- 对于每个决赛室,需要一个存储-container来存放该组内所有的参赛队,并决定先后顺序。
- 叫号系统需要是一个具有时序,并按规定顺序调用各组队列/容器中的参赛队的程序。
- 考虑到并发性和可扩展性,建议将各项任务设为多线程进行执行。
- 如何实现决赛叫号系统?
实现决赛叫号系统的基本思路如下:
- 1)设置9个决赛室,每个室内设定一个队列(FIFO)分别存储相应赛事类别参赛队;
- 2)每次比赛开始时,将所有参赛队划分到对应队列中,并根据规定顺序进入调度状态;
- 3)准备好结果显示界面,在进出场比赛时更新参赛队状态;
- 4)按照规定顺序分别从9个队列中取出每个参赛队,显示其进出场时间,并判断是否还有下一个参赛队可以进场;
- 5)如果当前所有室内参赛队已经进出完毕,则结束整个比赛。
对于c
本次任务的校园导游程序应该实现以下基本功能:
- 提供地图定位服务,可以为参赛者在校园地图上选取目标位置。
- 提供路径规划,查询任意两个目的地之间最短的行驶路线。
- 支持多种查询方式,包括校园地图上地点搜索、建筑物功能介绍查询等。
- 显示相关指示和提示信息,如路径长度、时间预算等。
- 校园导游程序需要哪些元素来实现?
- 需要利用地图软件提供的地理位置信息完成地图显示、目标定位等功能。
- 需要对校园地图的路径网络进行建模,并利用起点和终点之间的路径计算公式计算最小直线距离。
- 为了提供更好的用户体验,考虑使用图形化界面,并引入多种交互手段(如按钮、下拉框等)操作以方便用户。
- 对于各个建筑物,应当提供其名称、图片及相关介绍资料等。
以下是部分代码:(注:代码不是连续的,且并不完整)
// 按照参赛学校名称查找队伍
void searchBySchool(const std::vector<Team>& teams) {
std::string school;
std::cout << "请输入要查找的参赛学校名称:";
std::cin >> school;
std::map<std::string, std::vector<Team>> schoolTeams;// 创建一个映射,将参赛学校名称与团队向量关联起来
for (const Team& team : teams) {// 遍历给定的团队列表
if (team.school == school) {// 检查团队的学校是否与输入的学校名称匹配
schoolTeams[team.eventCategory].push_back(team);// 将符合条件的团队添加到相应赛事类别的团队向量中
}
}
if (schoolTeams.empty()) {
std::cout << "未找到该学校参赛的团队!" << std::endl;// 检查是否找到符合条件的团队
}
else {
std::cout << "该学校参赛的团队基本信息:" << std::endl;// 输出未找到团队的提示信息
for (auto& entry : schoolTeams) {// 遍历按赛事类别分组的团队信息
std::cout << "赛事类别:" << entry.first << std::endl;
std::cout << "参赛团队信息:" << std::endl;
const std::vector<Team>& teams = entry.second;// 获取当前赛事类别下的团队向量
for (const Team& team : teams) {// 遍历当前赛事类别下的团队
std::cout << "参赛队编号:" << team.teamNumber << ",参赛作品名称:" << team.projectName << std::endl;
}
}
}
}
//————————————————————————-----------------决赛室代码
// 参赛队伍的结构体
struct Teams {
int teamIds;
string projectNames;
string schools;
string categorys;
string participantss;
string coachs;
};
// 用于比较参赛队伍的辅助函数
bool compareTeams(const Teams& team1, const Teams& team2) {
return team1.teamIds < team2.teamIds;
}
// 决赛室叫号系统类
class FinalsCallSystem {
private:
map<string, vector<Teams>> categoryTeams; // 按赛事类别存储参赛队伍
vector<queue<Teams>> finalsRooms; // 存储决赛室及其队伍队列
public:
// 从文件中读取参赛队伍信息
void readTeamInfo(const string& filename) {
ifstream file(filename);
string line;
while (getline(file, line)) {
stringstream ss(line);
Teams team;
ss >> team.teamIds >> team.projectNames >> team.schools >> team.categorys >> team.participantss >> team.coachs;
categoryTeams[team.categorys].push_back(team);
}
file.close();
// 将每个赛事类别的参赛队伍按队伍编号排序
for (auto& categorys : categoryTeams) {
sort(categorys.second.begin(), categorys.second.end(), compareTeams);
}
}
// 模拟决赛叫号过程
void simulateFinals() {
int numRooms = 9; // 决赛室数量
int roomNumber = 1; // 当前决赛室编号
// 计算每个决赛室应分配的赛事类别数量
int numCategoriesPerRoom = categoryTeams.size() / numRooms;
int remainingCategories = categoryTeams.size() % numRooms;
auto categoryIter = categoryTeams.begin();
// 初始化决赛室容器
finalsRooms.resize(numRooms);
// 分配赛事类别到决赛室
for (int i = 0; i < numRooms; i++) {
int numCategories = numCategoriesPerRoom;
if (remainingCategories > 0) {
numCategories++;
remainingCategories--;
}
cout << "决赛室 " << roomNumber << ":";
// 将赛事类别的参赛队伍分配到当前决赛室
for (int j = 0; j < numCategories; j++) {
const auto& categorys = *categoryIter;
const vector<Teams>& teams = categorys.second;
// 输出当前赛事类别的参赛队伍
for (const auto& team : teams) {
finalsRooms[i].push(team);
cout << team.teamIds << " ";
}
categoryIter++;
}
cout << endl;
roomNumber++;
}
cout << "模拟比赛开始:" << endl;
// 模拟比赛过程
while (!finalsRooms.empty()) {
for (int i = 0; i < finalsRooms.size(); i++) {
if (!finalsRooms[i].empty()) {
const Teams& team = finalsRooms[i].front();
cout << "决赛室 " << (i + 1) << ":参赛队伍 " << team.teamIds << " 进场" << endl;
finalsRooms[i].pop();
}
}
}
cout << "比赛结束。" << endl;
}
};
void ShortestPath(int source, int destination) {
// 使用优先队列来选择下一个要处理的节点,按照距离排序
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
// 存储从起点到每个节点的最短距离
vector<int> distance(campusMap.size(), INF);
// 存储每个节点在最短路径中的前一个节点
vector<int> previous(campusMap.size(), -1);
// 将起点加入优先队列,并将其距离设置为0
pq.push({ 0, source });
distance[source] = 0;
// 开始寻找最短路径
while (!pq.empty()) {
int u = pq.top().second;// 获取优先队列中距离最小的节点
int dist = pq.top().first;// 获取距离
pq.pop();
// 弹出队列中的节点
// 如果当前节点的距离大于已知的最短距离,则忽略
if (dist > distance[u]) {
continue;
}
// 遍历当前节点的所有邻居节点
for (auto neighbor : campusMap[u].neighbors) {
int v = neighbor.first;
int weight = neighbor.second;
// 如果经过当前节点到达邻居节点的距离更短,则更新最短距离和前一个节点
if (distance[u] + weight < distance[v]) {
distance[v] = distance[u] + weight;// 更新最短距离
previous[v] = u;// 更新前一个节点
pq.push({ distance[v], v });// 将邻居节点加入优先队列,以便后续处理
}
}
}
// 检查是否存在路径
if (distance[destination] == INF) {
cout << "No path exists from " << campusMap[source].name << " to " << campusMap[destination].name << endl;
return;
}
// 构建路径
// 现在可以通过previous数组来构建最短路径
// 根据目标节点的previous数组回溯路径,直到达到起点
vector<int> path;
int current = destination;
while (current != -1) {
path.push_back(current);
current = previous[current];
}
reverse(path.begin(), path.end());// 最短路径是倒序的,所以需要反转它
// 打印地图
cout << "Campus Map:" << endl;
cout << "北门1——100————海韵湖2" << endl;
cout << " |200 \\" << endl;
cout << " | \\" << endl;
cout << " 计算机学院3 \\" << endl;
cout << " | \\900" << endl;
cout << " | 500 \\" << endl;
cout << " | \\" << endl;
cout << " | \\" << endl;
cout << " 文理大楼4—100—笃学楼5—50—图书馆6" << endl;
cout << " / \\" << endl;
cout << " / 50 \\100" << endl;
cout << " 明德楼7 ————900———— 东食堂8" << endl;
cout << " /400 \\" << endl;
cout << " / \\400" << endl;
cout << "西食堂9——200— —— ———————— 体育馆10" << endl;
cout << endl;
// 输出路径信息// 输出最短路径
cout << "Shortest Path from " << campusMap[source].name << " to " << campusMap[destination].name << ":" << endl;
for (int i = 0; i < path.size(); i++) {
cout << campusMap[path[i]].name;
if (i != path.size() - 1) {
cout << " -> ";
}
}
cout << endl;
cout << "Total Distance: " << distance[destination] << endl;
}