#题解题目分析本题是一个高尔夫球赛奖金分配问题。题目要求根据给定的总奖金purse、前707070名的奖金百分比、以及球员的比赛成绩计算出最终获得奖金的球员名单及其应得的奖金金额。主要规则如下所有球员至少完成前两轮363636洞除非被DQ取消资格。前两轮结束后取前707070名含并列晋级后两轮。晋级球员再打两轮按727272洞总成绩排名分配奖金。奖金百分比已给定且总和为100%100\%100%。业余球员名字后有*不能获得奖金其“赢得”的奖金顺延给下一位非业余球员。若有并列将对应名次的奖金池平分给并列的非业余球员。若晋级后有人DQ则只分配实际完赛的名次奖金。只输出晋级后两轮的球员以及DQ球员放在最后总分栏填DQ。解题思路数据结构设计定义一个结构体player存储每位球员的信息姓名、四轮成绩、总成绩、排名、完成轮数是否为业余、是否并列、是否获奖、奖金金额主要步骤读取输入先读测试用例数。对于每个用例读入总奖金money和前707070名的奖金百分比转换为小数存储。读入球员人数再逐行读取每个球员的信息调用parseToPlayer解析成绩和业余标识。第一轮筛选363636洞晋级计算完成至少两轮球员的前两轮总成绩。按总成绩升序排序取前707070名含并列第707070名。第二轮筛选727272洞完赛晋级球员中完成四轮的进入最终排名。未完成四轮的放入DQ列表。奖金分配按727272洞总成绩升序排序。按非业余球员顺序分配奖金百分比跳过业余。处理并列同一成绩的球员中将对应名次的百分比之和除以非业余人数再乘以总奖金。业余球员不参与奖金分配也不在排名后加T。输出先输出获奖球员按排名顺序格式严格按题目要求。再输出DQ球员按完成轮数降序、总成绩升序、姓名升序。细节注意奖金百分比读入时需除以100100100输出时再乘以总奖金。美元金额保留两位小数。并列标志T仅当两个或以上非业余球员成绩相同时才添加。DQ球员的TOTAL列输出DQ其余轮次成绩为空不输出数字。多用例之间输出一个空行。代码实现// PGA Tour Prize Money// UVa ID: 207// Verdict: Accepted// Submission Date: 2016-04-26// UVa Run Time: 0.050s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;constintDQ-1;// 表示取消资格或未完成该轮structplayer{string name;// 球员姓名intrd1,rd2,rd3,rd4;// 四轮成绩inttotal;// 总成绩36洞或72洞intplace;// 最终排名intround;// 完成的轮数boolamateur;// 是否为业余球员booltie;// 是否为并列仅非业余boolprized;// 是否获得奖金doubleprize;// 奖金金额};boolprintBlankLinefalse;// 控制用例间空行vectorplayerplayers;// 所有球员vectordoublepercents;// 前70名的奖金百分比小数形式doublemoney;// 总奖金// 按总成绩升序相同则按姓名升序boolcmp(player a,player b){if(a.totalb.total)returna.nameb.name;elsereturna.totalb.total;}// 用于DQ球员排序先按完成轮数降序再按cmpboolcmp2(player a,player b){if(a.roundb.round)returncmp(a,b);elsereturna.roundb.round;}// 主处理函数筛选、分配奖金、输出voidallocate(){if(printBlankLine)cout\n;elseprintBlankLinetrue;// 打印表头coutsetw(21)leftPlayer Name;coutsetw(10)leftPlace;coutsetw(5)leftRD1;coutsetw(5)leftRD2;coutsetw(5)leftRD3;coutsetw(5)leftRD4;coutsetw(10)leftTOTAL;coutMoney Won\n;cout-----------------------------------------------------------------------\n;// ---- 36洞晋级筛选 ----vectorplayerdq;vectorplayerfirstcut;for(inti0;iplayers.size();i)if(players[i].round2){players[i].totalplayers[i].rd1players[i].rd2;firstcut.push_back(players[i]);}sort(firstcut.begin(),firstcut.end(),cmp);// 取前70名含并列if(firstcut.size()70){intlast;for(last70;lastfirstcut.size();last)if(firstcut[last].totalfirstcut[69].total)continue;elsebreak;firstcut.erase(firstcut.begin()last,firstcut.end());}// ---- 72洞完赛筛选 ----vectorplayersecondcut;for(inti0;ifirstcut.size();i){if(firstcut[i].round4){firstcut[i].total(firstcut[i].rd3firstcut[i].rd4);firstcut[i].prizedfalse;firstcut[i].tiefalse;secondcut.push_back(firstcut[i]);}elsedq.push_back(firstcut[i]);// 晋级但未完成全部四轮}sort(secondcut.begin(),secondcut.end(),cmp);// ---- 分配奖金百分比跳过业余 ----for(inti0,index0;isecondcut.size()index70;i)if(!secondcut[i].amateur){secondcut[i].prizepercents[index];secondcut[i].prizedtrue;}// ---- 处理并列及最终奖金计算 ----for(inti0,place1;isecondcut.size();){intcounter0,prizedPlayers0,noAmateurs0;doubleprizeAllocate0.0;// 统计相同成绩的球员while((icounter)secondcut.size()secondcut[icounter].totalsecondcut[i].total){if(!secondcut[icounter].amateursecondcut[icounter].prized)prizedPlayers;if(!secondcut[icounter].amateur)noAmateurs;if(secondcut[icounter].prized)prizeAllocatesecondcut[icounter].prize;counter;}if(counter1){if(prizedPlayers0)prizeAllocate/noAmateurs;// 平均分配百分比之和prizeAllocate*money;// 换算为实际奖金for(intj0;jcounter;j){secondcut[ij].placeplace;if(!secondcut[ij].amateurprizedPlayers0){secondcut[ij].tienoAmateurs1;// 多于1个非业余才加Tsecondcut[ij].prizedtrue;secondcut[ij].prizeprizeAllocate;}}placecounter;icounter;}else{secondcut[i].placeplace;secondcut[i].tiefalse;secondcut[i].prize*money;place;i;}}// ---- 输出获奖球员 ----for(inti0;isecondcut.size();i){coutsetw(21)leftsecondcut[i].name;string standingto_string(secondcut[i].place)(secondcut[i].tie?T:);coutsetw(10)leftstanding;coutsetw(5)leftsecondcut[i].rd1;coutsetw(5)leftsecondcut[i].rd2;coutsetw(5)leftsecondcut[i].rd3;coutsetw(5)leftsecondcut[i].rd4;if(secondcut[i].prized){coutsetw(10)leftsecondcut[i].total;cout$;coutsetw(9)rightfixedsetprecision(2)secondcut[i].prize;}elsecoutsecondcut[i].total;cout\n;}// ---- 输出DQ球员 ----// 先计算已完成的轮次总分用于排序for(inti0;idq.size();i)dq[i].totaldq[i].rd3!DQ?dq[i].rd3:0;sort(dq.begin(),dq.end(),cmp2);for(inti0;idq.size();i){coutsetw(21)leftdq[i].name;coutsetw(10)left;coutsetw(5)left(dq[i].rd1!DQ?to_string(dq[i].rd1):);coutsetw(5)left(dq[i].rd2!DQ?to_string(dq[i].rd2):);coutsetw(5)left(dq[i].rd3!DQ?to_string(dq[i].rd3):);coutsetw(5)left(dq[i].rd4!DQ?to_string(dq[i].rd4):);coutDQ\n;}}// 去除字符串首尾空白stringtrim(string line){while(line.length()isblank(line.back()))line.erase(line.end()-1);while(line.length()isblank(line.front()))line.erase(line.begin());returnline;}// 解析一行输入为player结构体playerparseToPlayer(string line){// 确保长度至少32字符不足补空格while(line.length()32)line ;player x;x.nameline.substr(0,20);x.amateurtrim(x.name).back()*;// 名字末尾有*表示业余x.rd1DQ;x.rd2DQ;x.rd3DQ;x.rd4DQ;x.round0;string rd1trim(line.substr(20,3));string rd2trim(line.substr(23,3));string rd3trim(line.substr(26,3));string rd4trim(line.substr(29,3));// 逐轮解析遇到DQ则停止if(rd1!DQ){x.rd1stoi(rd1);x.round;}elsereturnx;if(rd2!DQ){x.rd2stoi(rd2);x.round;}elsereturnx;if(rd3!DQ){x.rd3stoi(rd3);x.round;}elsereturnx;if(rd4!DQ){x.rd4stoi(rd4);x.round;}returnx;}intmain(){cin.tie(0);cin.sync_with_stdio(false);intcases0;cincases;while(cases--){players.clear();percents.clear();cinmoney;doublepercent;for(inti1;i70;i){cinpercent;percents.push_back(percent/100.0);// 转换为小数}inttotalPlayers;cintotalPlayers;cin.ignore();string line;for(inti1;itotalPlayers;i){getline(cin,line);players.push_back(parseToPlayer(line));}allocate();}return0;}