题意:
读入各个球队的名字, 和球队之间比赛的进球数, 要求统计各个球队的比赛总场数, 总得分等信息, 按以下优先级顺序进行输出:
1. 最高得分
2. 最多胜利场次
3. 最多净胜球数(进球-失球)
4. 最多进球数
5. 最少比赛场数
6. 球队名字典序, 小的排前面(比较时不区分大小写)
注意: scored 3 goals 指的是进球数为 3, 不是得分 3; 看题目的时候这个理解错了, 纠结了好久, 无从下手.
思路:
1. 读入一行, 按 # 拆分出球队名和进球数.
2. 计算得分, 净胜球等信息.
3. 根据重载的 > 进行排序, 比较规则如题意所示.
4. 按顺序进行输出.
要点:
1. 重载 > 可以是成员函数, 重载 << 时必须是友元函数, 因为其要接收一个 ostream& 的参数. ???
2. 对于 if, for, 如果想不写{}, 那么其一行写完的句子必须简短到可以直接补在 if, for 后面, 形成一行.
题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=1135
代码:
# include <iostream> # include <string> # include <cstdio> # include <cstring> # include <vector> # include <algorithm> # include <cctype> # include <iterator> # include <assert.h> # include <map> using namespace std; // scored 3 goals 指的是进球数为 3, 不是得分 3 // 遍历 map // 重载 <, <<(只支持 friend?) // distance 取两个 iterator 之间的距离 class TeamRecord { public: TeamRecord(const string& teamName): scoreWin_(3), scoreTie_(1), scoreLoss_(0) { teamName_ = teamName; teamNameUpper_ = teamName_; transform(teamName_.begin(), teamName_.end(), teamNameUpper_.begin(), ::toupper); win_ = 0; tie_ = 0; loss_ = 0; goalScored_ = 0; goalAgainst_ = 0; } // 羸、平、输 void win() { ++win_; } void tie() { ++tie_; } void loss() { ++loss_; } // 进、丢球数 void scored(const int goal) { goalScored_ += goal; } void against(const int goal) { goalAgainst_ += goal; } // 总分数 int getPoints() const { return win_*scoreWin_ + tie_*scoreTie_ + loss_*scoreLoss_; } int getWin() const { return win_; } int getGoalDifference() const { return goalScored_ - goalAgainst_; } int getGoalScored() const { return goalScored_; } int getNumGames() const { return win_ + tie_ + loss_; } string getTeamNameUpper() const { return teamNameUpper_; } // 转成题目需要的输出 friend ostream& operator<<(ostream& os, const TeamRecord& tr); // 重载 > 符号, 按以下规则 /* Most points earned. Most wins. Most goal difference (i.e. goals scored - goals against) Most goals scored. Less games played. Lexicographic order. */ bool operator> (const TeamRecord& right) const { if (getPoints() > right.getPoints()) return true; if (getPoints() < right.getPoints()) return false; if (getWin() > right.getWin()) return true; if (getWin() < right.getWin()) return false; if (getGoalDifference() > right.getGoalDifference()) return true; if (getGoalDifference() < right.getGoalDifference()) return false; if (getGoalScored() > right.getGoalScored()) return true; if (getGoalScored() < right.getGoalScored()) return false; // 这里是不同的,要参赛参少的排前面 if (getNumGames() < right.getNumGames()) return true; if (getNumGames() > right.getNumGames()) return false; // 名字比较时不区分大小写, 按字典序,小的排前面 return (getTeamNameUpper() < right.getTeamNameUpper()); } private: string teamName_; string teamNameUpper_; int win_; int tie_; int loss_; int goalScored_ ; // 进球数 int goalAgainst_; // 丢球数 const int scoreWin_; // 羸了 3 分 const int scoreTie_; // 平了 1 分 const int scoreLoss_; // 输了 0 分 }; ostream& operator<<(ostream& os, const TeamRecord& tr) { char temp[500]; sprintf(temp, "%s %dp, %dg (%d-%d-%d), %dgd (%d-%d)", tr.teamName_.c_str(), tr.getPoints(), tr.win_ + tr.tie_ + tr.loss_, tr.win_, tr.tie_, tr.loss_, tr.goalScored_ - tr.goalAgainst_, tr.goalScored_, tr.goalAgainst_); os << temp; return os; } // 比较两个 TeamRecord bool greaterRank(const TeamRecord* tr1, const TeamRecord* tr2) { return (*tr1) > (*tr2); } // 将 Brazil#2@1#Scotland 格式中的 teamName, goals 分解出来 void splitTeamGoals(const string& line, map<string, TeamRecord*>& teamRecords) { size_t pos1 = line.find("#", 0); size_t pos2 = line.find("@", 0); size_t pos3 = line.find("#", pos2); string teamName1 = line.substr(0, pos1); int goals1 = atoi(line.substr(pos1+1, pos2-pos1-1).c_str()); string teamName2 = line.substr(pos3+1, line.size()-pos3-1); int goals2 = atoi(line.substr(pos2+1, pos3-pos2-1).c_str()); TeamRecord* tr1 = teamRecords[teamName1]; TeamRecord* tr2 = teamRecords[teamName2]; if (goals1 > goals2) { // 羸 tr1->win(); tr2->loss(); } else if (goals1 < goals2) { // 负 tr1->loss(); tr2->win(); } else { // 平 tr1->tie(); tr2->tie(); } // 进球记录 tr1->scored(goals1); tr1->against(goals2); tr2->scored(goals2); tr2->against(goals1); } int main(int argc, char const *argv[]) { #ifndef ONLINE_JUDGE freopen("10194_i.txt", "r", stdin); freopen("10194_o.txt", "w", stdout); #endif int numTournament; cin >> numTournament; cin.ignore(); // cin 后接 getline, 一定要有这个 while (numTournament--) { string tournamentName; getline(cin, tournamentName); cout << tournamentName << endl; // 读入球队名 int numTeams; cin >> numTeams; cin.ignore(); vector<string> teamNames; map<string, TeamRecord*> teamRecords; while (numTeams--) { string teamName; getline(cin, teamName); teamNames.push_back(teamName); TeamRecord* tr = new TeamRecord(teamName); teamRecords[teamName] = tr; } // 读入并分析比赛记录 int numGames; cin >> numGames; cin.ignore(); while (numGames--) { string line; getline(cin, line); splitTeamGoals(line, teamRecords); } vector<TeamRecord*> sortedTeamRecords; map<string, TeamRecord*>::iterator it; for (it = teamRecords.begin(); it != teamRecords.end(); ++it) { TeamRecord* tr = it->second; sortedTeamRecords.push_back(tr); } // 使用自定义函数进行排序 sort(sortedTeamRecords.begin(), sortedTeamRecords.end(), greaterRank); int ordTeam = 0; vector<TeamRecord*>::iterator it1; for (it1 = sortedTeamRecords.begin(); it1 != sortedTeamRecords.end(); ++it1) { cout << ++ordTeam << ") " << **it1 << endl; delete (*it1); // 输出后就可以释放空间了 } if (numTournament > 0) // 最后不能再输出 回车,否则 WA cout << endl; } return 0; }
环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE