唱歌比赛

某学校举行一场唱歌比赛,共有24个人参加,按参加顺序设置参赛号(参赛号为100至123)。每个选手唱完一首歌之后,由10个评委分别打分。该选手的最终得分是去掉一个最高分和一个最低分,求得剩下的8个评分的平均分。
 - 比赛共三轮,前两轮为淘汰赛,第三轮为决赛。选手的名次按得分降序排列,若得分一样,按参赛号升序排名。
-  第一轮分为4个小组,根据参赛号顺序依次划分,比如100-105为一组,106-111为第二组,依次类推,每组6个人,每人分别按参赛号顺序演唱。当小组演唱完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
-  第二轮分为2个小组,每组6人,每个人分别按参赛号顺序演唱。当小组演唱完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
 -   第三轮只剩下6个人,本轮为决赛,不淘汰选手,本轮目的是赛出每个人的名次。该6人按参赛号顺序分别演唱。

1. 请打印出所有选手的名字与参赛号,并以参赛号的升序排列。
2. 请打印出第1轮和第2轮淘汰赛中,各小组选手的名字与选手得分,并以名次的顺序排列。
3. 请打印出第1轮淘汰赛中被淘汰的歌手的名字(不要求打印顺序)。
4. 请打印出第2轮淘汰赛中被淘汰的歌手的分数,并以名次的降序排列。

#pragma once

#include <string>
using namespace std;

struct Singer
{
    string strName;     //名字
    int iLatestScore;   //最新得分
};
#pragma once
#include <iostream>
#include <algorithm>
#include "Singer.h"
#include <vector>
#include <map>
#include <list>
#include <deque>
#include <set>
#include <numeric>
#include <functional>
#include <iostream>  
#include <algorithm>  
#include <map>  
#include <set>  
#include <vector>  
#include <queue>  
#include <stack>  
#include <cstring>  
#include <cstdio>  
#include <cstdlib>  
#include <cmath> 
#include <ctime>
using namespace std;

class CSingingCompetition
{
public:
    CSingingCompetition(void);
    virtual ~CSingingCompetition(void);

//对外开放的成员方法
public:
    //报名参加比赛
    void JoinCompetition();

    //第一轮淘汰赛
    void FirstKnockout();

    //第二轮淘汰赛
    void SecondKnockout();

    //决赛
    void Finals();

//不对外开放的私有成员方法
private:
    //生成歌手的分数
    void MakeScore(Singer &singer);

    //打印当前小组的分数
    void PrintGroupScore();

    //在当前小组中淘汰歌手
    void EraseInCurGroup();

    //在剩余歌手中删除歌手
    void EraseInRemainingID(list<int>::iterator it);

    //淘汰赛
    void Knockout();

//私有成员变量
private:
    map<int, Singer> m_mapSinger;       //所有的参赛ID与歌手的映射集合。int:参赛ID,Singer:参加比赛的歌手。
    list<int> m_lstRemainingID;         //剩余歌手(没被淘汰的歌手)的参赛ID。int:剩余歌手的参赛ID。
    multimap<int, int, greater<int> >  m_mltmapCurGroup;    //当前演唱小组的歌手分数与歌手参赛ID的映射集合。第一个int: 歌手分数;第二个int: 歌手参赛ID;greater<int>: 函数对象,用于歌手分数的降序排列。
    vector<int> m_vecIDBeEliminatedInFirstRound;            //第一轮淘汰赛中被淘汰的歌手参赛的集合。int: 歌手的参赛号。
    multiset<int> m_mltsetScoreBeEliminatedInSecondRound;   //第二轮淘汰赛中被淘汰的歌手分数的集合。int: 歌手的分数。

    int m_iRound;       //第几轮比赛,值为1:第一轮;值为2:第二轮;值为3:第三轮。
};

#include "SingingCompetition.h"

CSingingCompetition::CSingingCompetition(void)
{
    //还没开始比赛,比赛轮数设置为0
    m_iRound = 0;

    //设置随机种子
    srand ( (unsigned)time ( 0 ) );
}

CSingingCompetition::~CSingingCompetition(void)
{
}

//报名参加比赛
void CSingingCompetition::JoinCompetition()
{
    if (m_iRound == 0)
    {
        string strNameBaseSource("ABCDEFGHIJKLMNOPQRSTUVWXYZ");  //名字组成元素的来源

        //随机排序名字组成元素的来源
        //random_shuffle(strNameBaseSource.begin(), strNameBaseSource.end());

        for (int i=0; i<24; ++i)
        {
            //获取参加比赛的歌手名字
            string strExt(1,strNameBaseSource[i]);

            //构造歌手对象
            Singer singer;
            singer.iLatestScore = 0;
            singer.strName = "选手";
            singer.strName += strExt;

            //录入参加比赛的歌手
            m_mapSinger.insert(pair<int, Singer>(i+100, singer));
            m_lstRemainingID.push_back(i+100);
        }

        //打印参加比赛的歌手名字与参赛号
        printf("*******************************************************\n");
        printf("参加比赛的歌手名字与参赛号:\n");
        for (map<int,Singer>::iterator it = m_mapSinger.begin(); it!=m_mapSinger.end(); ++it)
        {
            printf("%s,参赛号:%d\n", it->second.strName.c_str(), it->first);
        }
        printf("\n");
    }
}

//第一轮淘汰赛
void CSingingCompetition::FirstKnockout()
{
    if (m_iRound == 0)
    {
        m_iRound = 1;

        //进行淘汰赛
        Knockout();

        printf("第%d轮淘汰赛中被淘汰的歌手的名字:\n", m_iRound);
        for (vector<int>::iterator it=m_vecIDBeEliminatedInFirstRound.begin(); 
            it!=m_vecIDBeEliminatedInFirstRound.end(); ++it)
        {
            printf("%s ", m_mapSinger[*it].strName.c_str());
        }
        printf("\n");
        printf("\n");
    }
}

//第二轮淘汰赛
void CSingingCompetition::SecondKnockout()
{
    if (m_iRound == 1)
    {
        m_iRound = 2;

        //进行淘汰赛
        Knockout();

        printf("第%d轮淘汰赛中被淘汰的歌手的分数:\n", m_iRound);
        for (multiset<int>::iterator it=m_mltsetScoreBeEliminatedInSecondRound.begin(); it!=m_mltsetScoreBeEliminatedInSecondRound.end(); ++it)
        {
            printf("%d ", *it);
        }
        printf("\n");
        printf("\n");
    }
}

//决赛
void CSingingCompetition::Finals()
{
    if (m_iRound == 2)
    {
        m_iRound = 3;

        //第三轮决赛
        for (list<int>::iterator it=m_lstRemainingID.begin(); it!=m_lstRemainingID.end(); ++it)
        {
            //生成歌手的分数
            MakeScore(m_mapSinger[*it]);

            //记录当前小组歌手的得分情况,按分数降序排列
            m_mltmapCurGroup.insert(pair<int,int>(m_mapSinger[*it].iLatestScore, *it));
        }

        //打印小组决赛情况
        printf("*************小组决赛情况:*************\n");
        for (multimap<int,int, greater<int> >::iterator it=m_mltmapCurGroup.begin(); it!=m_mltmapCurGroup.end(); ++it)
        {
            printf("%s的得分:%d\n", m_mapSinger[it->second].strName.c_str() ,it->first);
        }
        printf("\n");

        //清除所有的数据
        m_mapSinger.clear();
        m_lstRemainingID.clear();
        m_vecIDBeEliminatedInFirstRound.clear();
        m_mltsetScoreBeEliminatedInSecondRound.clear();
        m_mltmapCurGroup.clear();
        m_iRound = 0;
    }
}

//生成歌手的分数
void CSingingCompetition::MakeScore(Singer &singer)
{
    deque<int> deqScore;

    //十个评委分别对歌手打分
    for (int i=0; i<10; ++i)
    {
        int iScore = 60 + rand()%40;
        deqScore.push_back(iScore);
    }

    //为十个评委的打分排序
    sort(deqScore.begin(), deqScore.end());

    //去掉一个最高分,去掉一个最低分
    deqScore.pop_front();
    deqScore.pop_back();

    //求八个评委打分的总和
    int iScoreSum = accumulate(deqScore.begin(), deqScore.end(), 0);

    //求八个评委打分的平均分
    int iScoreAverage = (int)(iScoreSum/deqScore.size());

    //给歌手设置得分
    singer.iLatestScore = iScoreAverage;
}

//打印当前小组的分数
void CSingingCompetition::PrintGroupScore()
{
    printf("小组得分情况:\n");
    for (multimap<int,int, greater<int> >::iterator it=m_mltmapCurGroup.begin(); it!=m_mltmapCurGroup.end(); ++it)
    {
        printf("%s的得分:%d\n", m_mapSinger[it->second].strName.c_str() ,it->first);
    }
    printf("\n");
}

//在当前小组中淘汰歌手
void CSingingCompetition::EraseInCurGroup()
{
    int iSingerLastIndexInGroup = 0;        //组内歌手的倒数索引
    while(iSingerLastIndexInGroup<3)
    {
        //获取当前演唱小组的最后一个元素的迭代器
        multimap<int,int,greater<int> >::iterator it=m_mltmapCurGroup.end();
        --it;

        ++iSingerLastIndexInGroup;

        if (m_iRound == 1)
        {
            //记录第一轮淘汰赛中被淘汰的歌手的参赛号
            m_vecIDBeEliminatedInFirstRound.push_back(it->second);
        }
        else if (m_iRound == 2)
        {
            //记录第二轮淘汰赛中被淘汰的歌手的分数
            m_mltsetScoreBeEliminatedInSecondRound.insert(m_mapSinger[it->second].iLatestScore);
        }

        //从当前演唱小组的集合容器中删除最后一个元素
        m_mltmapCurGroup.erase(it);
    }
}

//在剩余歌手中删除歌手
void CSingingCompetition::EraseInRemainingID(list<int>::iterator it)
{
    int iSingerReverseIndexInGroup = 0;     //逆向遍历的索引
    while(iSingerReverseIndexInGroup<6)
    {
        //查找逆向遍历迭代器所指的参赛ID所对应歌手的{分数,参赛ID}是否在当前演唱小组中
        multimap<int,int,greater<int> >::iterator itMltmapScoreToID = 
            find(m_mltmapCurGroup.begin(),m_mltmapCurGroup.end(), 
            multimap<int,int,greater<int> >::value_type(m_mapSinger[*it].iLatestScore, 
            *it));

        if (itMltmapScoreToID == m_mltmapCurGroup.end())
        {
            //没找到,从剩余歌手集合中删除该歌手的参赛号
            it = m_lstRemainingID.erase(it);
        }

        //逆向遍历的索引自增
        ++iSingerReverseIndexInGroup;

        //防止对容器的begin()迭代器进行--操作。
        if (it != m_lstRemainingID.begin())
        {
            --it;
        }
    }

    //清除该组的比赛记录存储,以便下一组比赛记录的存储
    m_mltmapCurGroup.clear();
}

//淘汰赛
void CSingingCompetition::Knockout()
{
    printf("*************第%d轮淘汰赛:*************\n", m_iRound);

    int iSingerIndex = 0;       //第几个歌手正在演唱,1代表第一个歌手,2代表第二个歌手。。。
    for (list<int>::iterator it=m_lstRemainingID.begin(); it!=m_lstRemainingID.end(); )
    {
        ++iSingerIndex;

        //生成歌手的分数
        MakeScore(m_mapSinger[*it]);

        //记录当前演唱小组歌手的得分情况,按分数降序排列
        m_mltmapCurGroup.insert(pair<int,int>(m_mapSinger[*it].iLatestScore, *it));

        if (iSingerIndex%6 == 0)
        {
            //小组演唱完毕,打印小组得分情况
            PrintGroupScore();

            //在当前小组中淘汰歌手
            EraseInCurGroup();

            //在剩余歌手中删除歌手
            EraseInRemainingID(it++);  //不可用++it代替,因为要转入自增之前的迭代器
        }
        else
        {
            ++it;
        }
    }
}
#include <iostream>
#include <string>
#include "SingingCompetition.h"
using namespace std;
int main(){
    CSingingCompetition c;

    c.JoinCompetition();
    c.FirstKnockout();
    c.SecondKnockout();
    c.Finals();

    return 0;
}

这里写图片描述
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值