需求:
某學校舉行一場唱歌比賽,共有24個人參加,按參加順序設置參賽號(參賽號爲100至123)。
每個選手唱完一首歌之後,由10個評委分別打分。該選手的最終得分是去掉一個最高分和一個最低分,求得剩下的8個評分的平均分。
比賽共三輪,前兩輪爲淘汰賽,第三輪爲決賽。選手的名次按得分降序排列,若得分一樣,按參賽號升序排名。
第一輪分爲4個小組,根據參賽號順序依次劃分,比如100-105爲一組,106-111爲第二組,依次類推,每組6個人,每人分別按參賽號
順序演唱。當小組演唱完後,淘汰組內排名最後的三個選手,然後繼續下一個小組的比賽。
第二輪分爲2個小組,每組6人,每個人分別按參賽號順序演唱。當小組演唱完後,淘汰組內排名最後的三個選手,然後繼續下一個小組的比賽。
第三輪只剩下6個人,本輪爲決賽,不淘汰選手,本輪目的是賽出每個人的名次。該6人按參賽號順序分別演唱。
#include "stdafx.h"
#include "stdio.h"
#include "string"
#include "vector"
#include "list"
#include "map"
#include "set"
#include "stack"
#include "deque"
#include <algorithm>//排序算法
#include "iostream"
#include <time.h>
#include <numeric>//求和函數
using namespace std;
/*
需求1、請打印出所有選手的名字與參賽號,並以參賽號的升序排列。
分析1、參賽號唯一,可以用map,參加比賽的時候對map進行賦值
需求2、請打印出第1輪和第2輪淘汰賽中,各小組選手的名字與選手得分,並以名次的順序排列
分析2、選手和得分又是關聯的,分數有可能一樣,可以考慮用multimap,需要定義兩個multimap,或者局部變量
流程是:分組,歌唱,評分,打印,更新list
分組:按照需要分組,6人一組,每一輪比賽流程一致,可以統一寫成一個函數
僞代碼:
Round = 1
start = 100
歌手IDlist來控制循環每一個歌手進行比賽
for i = 0,i < 6,i++
index = start + i
//唱歌:用Singer對象調用唱歌方法
//評分:獲取10的隨機評分值(??),用臨時變量deque來做記錄,sort排序一下,去掉最高和最低,然後求和平均,把平均分與這個歌手綁定 multimap
//歌手和分數綁定,分數有可能一樣,用multimap
endfor
//map自動排序,打印出這一組的選手的名字和得分
//根據得分,獲取晉級的和被淘汰的,把被淘汰的歌手名字用vector來存放
更新list
更新
需求3、請打印出第1輪淘汰賽中被淘汰的歌手的名字(不要求打印順序)。
在需求2的基礎上,把每組最低分的3個取出來,打印出來,更新list
需求4、請打印出第2輪淘汰賽中被淘汰的歌手的分數,並以名次的降序排列。
在需求2的基礎上,把每組最低分的3個取出來,打印出來,更新list
*/
//歌手類
class Singer /*: public Ponsen*/
{
public:
Singer() { m_SingerID = 0; m_LastScore = 0;
printf("Singer Singer() GetName:%s,GetAddress:%s \n", GetName().c_str(), GetAddress().c_str());
printf("\n");
}
Singer(string name, string addr, int id) :/*Ponsen(name, addr), */m_Name(name), m_Address(addr), m_SingerID(id) { m_LastScore = 0;
printf("Singer GetName:%s, GetAddress:%s GetSingerID() = %d \n", GetName().c_str(), GetAddress().c_str(), m_SingerID);
printf("\n");
}
Singer(const Singer & sing);
inline void SingSong() {
//printf("**歌手:%s, ID:%d 唱歌*********,最終得分爲%d \n", GetName().c_str(), m_SingerID , m_LastScore);
}
inline int GetSingerID() const { return m_SingerID; }
inline void SetSingerID(const int id) { m_SingerID = id; }
inline int GetScore() const{ return m_LastScore; }
inline void SetScore(const int score) { m_LastScore = score; }
inline string GetName() const { return m_Name; }
inline string GetAddress() const { return m_Address; }
inline void SetName(const string name)
{ m_Name = name; printf("Singer SetName(string) m_Name = %s \n", m_Name.c_str()); printf("\n"); }
inline void SetAddress(const string addr)
{ m_Address = addr; printf("Singer SetAddress(string) m_Address = %s \n", m_Address.c_str()); printf("\n"); }
private:
int m_SingerID;//歌手ID,唯一性
int m_LastScore;//最新分數
string m_Name;
string m_Address;
};
Singer::Singer(const Singer & sing)
{
//printf("Singer Singer(Singer&) GetName:%s,GetAddress:%s \n", GetName().c_str(), GetAddress().c_str());
printf("\n");
}
//比賽類
/*
數據結構和流程怎麼設計
利用STL中的容器和算法:vector,deque,quque,stack,list,map,multimap,set,multiset
方法:
1、報名:把ID和歌手類映射一起,把ID存放到list列表中
2、分組
3、比賽(1輪,2輪,決賽):傳入ID信息,
4、打印
*/
class SongCompetition
{
public:
//
SongCompetition()
{
//還沒開始比賽,比賽輪數設置爲0
m_iRound = 0;
//設置隨機種子
srand((unsigned)time(0));
}
void SignUp(const int, const int);
//構造函數
void SignUpConpetition(const int, const Singer&);
void FirstRound();
void SecondRound();
void LastRound();
private:
int m_iRound;//比賽次數,控制比賽流程
//爲什麼選用map,歌手id唯一性,id與歌手的關聯性
map<int, Singer, less<int>> m_SignUpInfoMap;//報名信息的Map,用一個ID綁定一個歌手
list<int> m_SingerList;//維護參賽ID,開始24人,每一輪比賽後刪除淘汰的選手,然後再
multimap<int, int, greater<int>> m_mltmapCurGroupInfo;//分數,ID,降序排列,
vector<int> m_vecEliminateSingerRO;//第一輪比賽淘汰的ID號
multiset<int> m_mtlsetEliminateSingerRT;//第二輪淘汰的ID號,需要順序
void PrintCurRoundInfo();
void RecordEliminateSinger();
void DelCurRoundSingerID(list<int>::iterator);
//唱歌得出分數函數
int SingleSongCp(Singer &);
void SingRound();
int MakeScore(const int id);
void PrintAllSignUpInfo();
};
void SongCompetition::FirstRound()
{
if (m_iRound == 0)
{
m_iRound = 1;
printf("**第%d輪歌唱比賽** \n", m_iRound);
SingRound();
//打印被淘汰的歌手的名字,由ID進行綁定
for (vector<int>::iterator it = m_vecEliminateSingerRO.begin(); it != m_vecEliminateSingerRO.end(); it++)
{
printf("被淘汰的歌手的名字爲:%s \n", m_SignUpInfoMap[*it].GetName().c_str());
}
}
}
void SongCompetition::SecondRound()
{
if (m_iRound == 1)
{
m_iRound = 2;
printf("\n");
printf("**第%d輪歌唱比賽** \n", m_iRound);
SingRound();
//打印第2輪被淘汰的歌手的分數,按照順序排列
for (multiset<int>::iterator it = m_mtlsetEliminateSingerRT.begin(); it != m_mtlsetEliminateSingerRT.end(); it++)
{
printf("被淘汰的歌手的分數:%d \n", *it);
}
}
}
void SongCompetition::LastRound()
{
if (m_iRound == 2)
{
m_iRound = 3;
printf("\n");
printf("**第%d輪歌唱比賽** \n", m_iRound);
SingRound();
}
m_SignUpInfoMap.clear();
m_SingerList.clear();
m_mltmapCurGroupInfo.clear();
m_vecEliminateSingerRO.clear();
m_mtlsetEliminateSingerRT.clear();
m_iRound = 0;
}
//在剩餘歌手中刪除歌手
void SongCompetition::DelCurRoundSingerID(list<int>::iterator it)
{
//輸入的是ID的迭代器,通過ID號查找當前分數-ID集合中的集合,
int index = 0;//逆向遍歷的索引
while (index < 6)//爲什麼是循環6次,
{
//查找逆向遍歷迭代器所指的參賽ID所對應歌手的{分數,參賽ID}是否在當前演唱小組中
multimap<int, int, greater<int>>::iterator itr =
find(m_mltmapCurGroupInfo.begin(),
m_mltmapCurGroupInfo.end(),
multimap<int, int, greater<int>>::value_type(m_SignUpInfoMap[*it].GetScore(), *it));
index++;
if (itr == m_mltmapCurGroupInfo.end())
{
//沒找到,從剩餘歌手集合中刪除該歌手的參賽號,因爲這個歌手已經被淘汰了,要更新list列表
it = m_SingerList.erase(it);//一定要用it接收返回值,返回值爲下一個迭代器
}
//防止對容器的begin()迭代器進行--操作。
if (it != m_SingerList.begin())
{
--it;
}
}
m_mltmapCurGroupInfo.clear();
}
/*
//函數功能:往map裏面插入數據
*/
void SongCompetition::SignUpConpetition(const int id, const Singer &sing)
{
////插入數據方法一,//用這個方法,遍歷的時候GetName內容爲空,GetAddress內容爲空,爲什麼呢
//m_SignUpInfoMap.insert(map<int, Singer>::value_type(id, sing));
//插入數據方法二,用這個方法,遍歷的時候GetName內容爲空,GetAddress內容爲空,爲什麼呢
//m_SignUpInfoMap.insert(pair<int, Singer>(id, sing));
m_SignUpInfoMap[id] = sing;//插入數據方法三
printf("\n");
}
void SongCompetition::PrintCurRoundInfo()
{
if (m_mltmapCurGroupInfo.size())
{
//printf("*****************第%組比賽結果如下*************** \n", m_iRound);
for (multimap<int, int, greater<int>>::iterator it = m_mltmapCurGroupInfo.begin(); it != m_mltmapCurGroupInfo.end(); it++)
{
//根據ID號找到歌手名字
printf("歌手:%s, 歌唱評分爲:%d \n", m_SignUpInfoMap[it->second].GetName().c_str(), it->first);
}
printf("\n");
}
}
void SongCompetition::SignUp(const int start, const int all)
{
for (int i = 1; i <= all; i++)
{
char strstart = 'A';//
string sFirstName(2, strstart + i);
//printf("sFirstName:%s \n", sFirstName.c_str());
Singer sing(sFirstName, "beijing", start + i);
sing.SetSingerID(start + i);
SignUpConpetition(start + i, sing);
m_SingerList.push_back(start + i);
printf("\n");
}
PrintAllSignUpInfo();
//Ponsen的屬性無法設置//////////////////////////////////////////////////////////////////////////////////////////////////
}
//分組
//定義接口:唱歌比賽函數,輸入ID,得出分數
int SongCompetition::SingleSongCp(Singer &sing)
{
if (1/*sing.GetSingerID > 100*/)
{
//printf("歌手%s ID:%d 準備唱歌", sing.GetName().c_str(), sing.GetSingerID());
int ret = MakeScore(sing.GetSingerID());
sing.SetScore(ret);
sing.SingSong();
return ret;
}
else
{
return 0;
}
}
//唱歌評分
int SongCompetition::MakeScore(const int id)
{
deque<int> deqSingScore;
//十個評委分別對歌手打分
for (int i = 0; i<10; ++i)
{
int iScore = 60 + rand() % 40;
deqSingScore.push_back(iScore);
//printf("評委%d對歌手%d進行評分,分數爲:%d", i, id, iScore);
}
//排序sort
sort(deqSingScore.begin(), deqSingScore.end());
//排除最高和最低分
deqSingScore.pop_front();
deqSingScore.pop_back();
//求和
int sum = accumulate(deqSingScore.begin(), deqSingScore.end(), 0);
//求平均分
return sum / deqSingScore.size();
}
void SongCompetition::RecordEliminateSinger()
{
int index = 0;
//已經排好序,直接拿最後三個數據
for (int i = 0; i < 3/*m_mltmapCurGroupInfo.size() / 2*/; i++)
{
multimap<int, int, greater<int>>::iterator itr = m_mltmapCurGroupInfo.end();
--itr;
if(m_iRound == 1)
m_vecEliminateSingerRO.push_back((itr)->second);//第一輪被淘汰的ID
if (m_iRound == 2)
m_mtlsetEliminateSingerRT.insert((m_SignUpInfoMap.at(itr->second).GetScore()));//第二輪淘汰的分數
//被淘汰的ID號爲
//printf("**被淘汰的歌手的ID號爲:%d \n", (itr)->second);
m_mltmapCurGroupInfo.erase(itr);//刪掉這個被淘汰的,剩下晉級的要用於維護list歌手列表
}
}
void SongCompetition::SingRound()
{
//m_iRound = 1;
int iSingerIndex = 0;
//printf("***********進行第%d輪唱歌比賽************** \n", m_iRound);
//參數選手信息
if (m_SingerList.size() > 0)
{
for (list<int>::iterator it = m_SingerList.begin(); it != m_SingerList.end();)
{
int ret = SingleSongCp(m_SignUpInfoMap[*it]);
m_mltmapCurGroupInfo.insert(pair<int, int>(ret, *it));//獲取當前組的分數,ID
if ((++iSingerIndex) % 6 == 0)//分組從1開始,1-6,7-12
{
//這裏是統計一個組的結果,分數排序,篩選,存放結果
printf("\n");
//排列當前組的名次
PrintCurRoundInfo();//打印信息:
if (m_iRound < 3)
{
RecordEliminateSinger();
DelCurRoundSingerID(it++);
}
else
{
it++;
}
}
else
{
++it;
}
}
}
}
//按照ID升序打印所有參賽選手信息
void SongCompetition::PrintAllSignUpInfo()
{
if (m_SignUpInfoMap.size())
{
for (map<int, Singer>::iterator it = m_SignUpInfoMap.begin(); it != m_SignUpInfoMap.end(); it++)
{
//pair<int, Singer> pr = *it;//用這個方法,GetName內容爲空,GetAddress內容爲空,爲什麼呢
printf("**參賽選手-編號:%d,姓名:%s, 地址:%s \r\n", it->first, it->second.GetName().c_str(), it->second.GetAddress().c_str());
}
}
}
int main()
{
SongCompetition m_SongCp;
m_SongCp.SignUp(100, 24);
m_SongCp.FirstRound();
m_SongCp.SecondRound();
m_SongCp.LastRound();
char inputchar;
cin >> inputchar;
return 0;
}