十、STL综合案例——学校演讲比赛
2018-07-04 本文已影响0人
木鱼_cc
1.比赛介绍
1) 某市举行一场演讲比赛(speech_contest),共有24人参加。比赛共三轮,前两轮为淘汰赛,第三轮为决赛
2) 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;
- 第一轮分为4个小组,每组6人。比如100-105一组,106-111二组,一次类推
- 没人分别按照抽签(draw)顺序演讲。当小组演讲完后,淘汰组内排名最后的三名宣说,然后进行下一个小组的比赛
- 第二轮分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
- 第三轮只剩下6个人,本轮为决赛,选出前三名
3) 比赛评分:10个评委打分,去除最低、最高分,求平均分
- 每个选手演讲完由10名评委打分。该选手的最终得分是去掉一个最高分和一个最低分
- 选手的名字按得分降序排列,若得分一样,按参赛号升序排名
4) 用STL编程,求解这个问题
- 请打印出所有选手的名字和参赛号,并以参赛号的升序排列
- 打印每一轮比赛后,小组比赛成绩和小组晋级名单
- 打印决赛前三名,选手名称、成绩
2.需求分析
//产生选手(ABCDEFGHIJKLMNOPQRSTUVWXYZ) 姓名、得分;选手编号
//第一轮 选手抽签 选手比赛 查看比赛结果
//第二轮 选手抽签 选手比赛 查看比赛结果
//第三轮 选手抽签 选手比赛 查看比赛结果
3. 实现思路
需要把选手信息,选手得分信息、选手比赛抽签信息、选手的晋级信息保存到容器中,需要涉及各个容器的类型。(相当于信息的数据库E-R图设计)
选手可以设计一个 Speaker(姓名和得分)
所有选手编号和选手信息,可以放在容器内:map<int,Speaker>
所有选手的编号信息,可以放在容器:vector<int> v1
中
第1轮晋级名单,可以放在容器vector<int> v2
中
第2轮晋级名单,可以放在容器vector<int> v3
中
第3轮晋级名单,可以放在容器vector<int> v4
中
每个小组的比赛得分信息,按照从小到大排序放在
multimap<成绩,编号,greater<int>>multimapGroup
也就是
multimap<int,int,greater<int>>multimapGroup
每个选手的得分,可以放在容器deque<int>dscore;
方便去除最低最高分
4.搭建框架
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
//定义选手类
class Speaker{
public:
string name;
int score[3];//保存3轮最终得分
};
//创建选手
void Create_Speaker(map<int,Speaker> &mapSpeaker,vector<int> &v1){
}
//选手抽签
int Random_SpeakerID(vector<int> &v1){
}
//选手比赛(第几轮,选手编号,比赛得分保存,晋级编号保存)
void Match_Speaker(int index,vector<int> &v1,map<int,Speaker> &mapSpeaker,vector<int> &v2){
}
//查看比赛结果(第一轮,结果保存容器,对应名字) 其实就是第一轮结果保存在了v2中,再利用mapSpeaker看名字
void Show_Match_Result(int index,vector<int> &v2,map<int,Speaker> &mapSpeaker){
}
int main(){
map<int,Speaker> mapSpeaker;//保存选手信息 根据编号
vector<int> v1;//保存第一轮参赛的编号
vector<int> v2;//第一轮比赛的晋级编号(第二轮比赛编号)
vector<int> v3;//第二轮晋级编号(第三名比赛编号)
vector<int> v4;//最终最终的前三名编号
//创建选手 24 名
Create_Speaker(mapSpeaker,v1);
//----------------------------第一轮比赛
//选手抽签
Random_SpeakerID(v1);//相当于把容器内的编号打乱就好了
//选手比赛 (第一轮,选手,比赛得分保存,编号保存)
Match_Speaker(1,v1,mapSpeaker,v2);
//查看比赛结果(第一轮,结果保存容器,对应名字) 其实就是第一轮结果保存在了v2中,再利用mapSpeaker看名字
Show_Match_Result(1,v2,mapSpeaker);
//----------------------------第二轮比赛
Random_SpeakerID(v2);//选手抽签
Match_Speaker(2,v2,mapSpeaker,v3);//选手比赛
Show_Match_Result(2,v3,mapSpeaker); //查看比赛结果
//----------------------------第三轮比赛
Random_SpeakerID(v3);//选手抽签
Match_Speaker(3,v3,mapSpeaker,v4);//选手比赛
Show_Match_Result(3,v4,mapSpeaker); //查看比赛结果
return 0;
}
5.完整代码
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <deque>
#include <numeric>
#include <functional>
using namespace std;
//定义选手类
class Speaker{
public:
string name;
int score[3];//保存3轮最终得分
};
//创建选手
void Create_Speaker(map<int,Speaker> &mapSpeaker,vector<int> &v1){
string nameseed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(int i = 0; i < 24;i++){
//创建选手对象
Speaker speaker;
speaker.name = "选手";
speaker.name += nameseed[i];
speaker.score[0] = 0;
speaker.score[1] = 0;
speaker.score[2] = 0;
//创建选手唯一的参赛编号
int SpeakerID = 100 + i;
mapSpeaker.insert(make_pair<int,Speaker>(SpeakerID,speaker));//保存选手信息
v1.push_back(SpeakerID);
}
}
//选手抽签
int Random_SpeakerID(vector<int> &v1){
random_shuffle(v1.begin(),v1.end());//在<algorithm>中
}
//选手比赛(第几轮,选手编号,比赛得分保存,晋级编号保存)
void Match_Speaker(int index,vector<int> &v1,map<int,Speaker> &mapSpeaker,vector<int> &v2){
multimap<int,int,greater<int>> mapGroup;//分数做key,id做value 就可以排序了
int indexTemp = 0;
int indexGroup = 0;//记录哪一组
for(vector<int>::iterator it = v1.begin();it != v1.end();it++){
indexTemp++;
deque<int> dscore;//保存评委10次得分
for (int i = 0; i < 10; ++i){
int score = 50 + rand() % 50;
dscore.push_back(score);
}
//排序
sort(dscore.begin(),dscore.end());//从小到大
//去除最高分
dscore.pop_back();//去除最高分
dscore.pop_front();//去除最低分
//求平均分 先累加
int totalscore = accumulate(dscore.begin(),dscore.end(),0);//在numeric中
int scoreavg = totalscore/dscore.size();
mapSpeaker[*it].score[index-1] = scoreavg;//*it就是编号 index-1才是分数
mapGroup.insert(make_pair<int,int>(scoreavg,*it));//保存分组信息
if (indexTemp % 6 == 0)
{
indexGroup++;
int highIndex = 0;
printf("第%d轮比赛成绩第%d组比赛成绩:\n",index,indexGroup);
for(multimap<int,int,greater<int>>::iterator it2 = mapGroup.begin();it2 != mapGroup.end();it2++){
highIndex++;
if (highIndex <= 3)
{
v2.push_back(it2->second);//保存前三名
}
cout<<"姓名:"<<mapSpeaker[it2->second].name<<" 分数:"<<mapSpeaker[it2->second].score[index-1]<<endl;
}
mapGroup.clear();//清空mapGroup
}
}
}
//查看比赛结果(第一轮,结果保存容器,对应名字) 其实就是第一轮结果保存在了v2中,再利用mapSpeaker看名字
void Show_Match_Result(int index,vector<int> &v2,map<int,Speaker> &mapSpeaker){
printf("第%d轮比赛晋级名单\n",index);
for(vector<int>::iterator it = v2.begin();it != v2.end();it++){
cout<<"姓名:"<<mapSpeaker[*it].name<<" 分数"<<mapSpeaker[*it].score[index-1]<<endl;
}
}
int main(){
map<int,Speaker> mapSpeaker;//保存选手信息 根据编号
vector<int> v1;//保存第一轮参赛的编号
vector<int> v2;//第一轮比赛的晋级编号(第二轮比赛编号)
vector<int> v3;//第二轮晋级编号(第三名比赛编号)
vector<int> v4;//最终最终的前三名编号
//创建选手 24 名
Create_Speaker(mapSpeaker,v1);
//----------------------------第一轮比赛
//选手抽签
Random_SpeakerID(v1);//相当于把容器内的编号打乱就好了
//选手比赛 (第一轮,选手,比赛得分保存,编号保存)
Match_Speaker(1,v1,mapSpeaker,v2);
//查看比赛结果(第一轮,结果保存容器,对应名字) 其实就是第一轮结果保存在了v2中,再利用mapSpeaker看名字
Show_Match_Result(1,v2,mapSpeaker);
//----------------------------第二轮比赛
Random_SpeakerID(v2);//选手抽签
Match_Speaker(2,v2,mapSpeaker,v3);//选手比赛
Show_Match_Result(2,v3,mapSpeaker); //查看比赛结果
//----------------------------第三轮比赛
Random_SpeakerID(v3);//选手抽签
Match_Speaker(3,v3,mapSpeaker,v4);//选手比赛
Show_Match_Result(3,v4,mapSpeaker); //查看比赛结果
return 0;
}
1.png