原题链接:https://vjudge.net/problem/UVA-207
分类:耐力
备注:排序和其他细节处理
前言:这是我第二次默写刘老师的代码了,真的崩溃,错一点点细节都不行,对着uDebug改来改去,总算是好了,好奇怪为什么把代码的输入方式改了就出问题了,以后有机会再回来看看吧。不得不说刘老师的代码越看越养眼。
另外还有数据生成器的博客在此:https://blog.csdn.net/richenyunqi/article/details/86429415?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
注意点:不要尝试修正精度,可能WA,uDebug才有精度问题。
题意
任务是为PGA(美国职业高尔夫球协会)巡回赛计算奖金。巡回赛分为4轮,其中所有选手都能打前两轮(除非中途取消资格),得分相加(越少越好),前70名(包括并列)晋级(make the cut)。所有晋级选手再打两轮,前70名选手(包括并列)有奖金。组委会事先会公布每个名次能拿的奖金比例。例如,若冠军比例是18%,总奖金是$1000000,则冠军奖金是$180000。
输入保证冠军不会并列。如果第k名有n人并列,则第k~n+k-1名的奖金比例相加后平均分给这n个人。奖金四舍五入到美分。所有业余选手不得奖金。例如,若业余选手得了第3名,则第4名会拿第3名的奖金比例。如果没取消资格的非业余选手小于70名,则剩下的奖金就不发了。
输入第一行为数据组数。每组数据前有一个空行,然后分为两部分。第一部分有71行(各有一个实数),第一行为总奖金,第i+1行为第i名的奖金比例。比例均保留4位小数,且总和为100%。第72行为选手数(最多144),然后每行一个选手,格式为:
Player name RD1 RD2 RD3 RD4
业余选手名字后会有一个“*”。犯规选手在犯规的那一轮成绩为DQ,并且后面不再有其他成绩。但是只要没犯规,即使没有晋级,也会给出4轮成绩(虽然在实际比赛中没晋级的选手只会有两个成绩)。输入保证至少有70个人晋级。
输出应包含所有晋级到后半段(make the cut)的选手。输出信息包括:选手名字、排名、各轮得分、总得分以及奖金数。没有得奖则不输出,若有奖金,即使奖金是$0.00也要输出,保留两位小数)。如果此名次至少有两个人获得奖金,应在名次后面加“T”。犯规选手列在最后,总得分为DQ,名次为空。如果有并列,则先按轮数排序,然后按各轮得分之和排序,最后按名字排序。两组数据的输出之间用一个空格隔开。
在上面紫书已经说的很详细了,唯一可能不太清楚的是:晋级的一定不包括一二轮犯规的,只输出晋级的,一旦晋级不管什么情况,他们有的数据全部输出并且无多余空格,分奖金的只有前70名职业选手,而第70名是可以并列的,所以能分奖金的人可能超过70个,如67名有10个并列,则一共66+10个人分奖金。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define REP(i,n) for(int i=0; i<(n);i++)
const int maxn = 144;
const int maxp = 70;
int T, n;
double all, per[maxp];
struct CPly {
char name[25];
int yu;
int sc36, sc72, dq;
int rd[4];
int rnds;
}ply[maxn];
bool cmp1(const CPly& a, const CPly& b) {
if (a.sc36 < 0 && b.sc36 < 0)return false;
if (a.sc36 < 0)return false;
if (b.sc36 < 0)return true;
return a.sc36 < b.sc36;
}
bool cmp2(const CPly& a, const CPly& b) {
if (a.dq && b.dq) {
if (a.rnds != b.rnds)return a.rnds > b.rnds;
if (a.sc72 != b.sc72)return a.sc72 < b.sc72;
return strcmp(a.name, b.name) < 0;
}
if (a.dq)return false;
if (b.dq)return true;
if (a.sc72 != b.sc72)return a.sc72 < b.sc72;
return strcmp(a.name, b.name) < 0;
}
int main(void) {
char s[40];
fgets(s, 40, stdin);
sscanf(s, "%d", &T);
while (T--) {
memset(ply, 0, sizeof(ply));
fgets(s, 40, stdin);
fgets(s, 40, stdin);
sscanf(s, "%lf", &all);
REP(i, maxp) {
fgets(s, 40, stdin);
sscanf(s, "%lf", &per[i]);
}
fgets(s, 40, stdin);
sscanf(s, "%d", &n);
REP(i, n) {
fgets(s, 40, stdin);
strncpy(ply[i].name, s, 20);
if (strchr(ply[i].name, '*'))ply[i].yu = 1;
REP(j, 4) {
char t[5] = { 0 };
REP(k, 3)t[k] = s[20 + j * 3 + k];
if (!sscanf(t, "%d", &ply[i].rd[j])) {
ply[i].rnds = j;
ply[i].dq = 1;
if (j < 2)ply[i].sc36 = -1;
break;
}
ply[i].sc72 += ply[i].rd[j];
if (j < 2)ply[i].sc36 += ply[i].rd[j];
}
}
sort(ply, ply + n, cmp1);
int cnt = min(n, 70);
while (cnt < n && ply[cnt - 1].sc36 == ply[cnt].sc36)cnt++;
sort(ply, ply + cnt, cmp2);
printf("Player Name Place RD1 RD2");
printf(" RD3 RD4 TOTAL Money Won\n");
printf("---------------------------------------");
printf("--------------------------------\n");
int i = 0, pos = 0;
while (i < cnt) {
if (ply[i].sc36 < 0) { i++; continue; }
if (ply[i].dq) {
printf("%s ", ply[i].name);
REP(j, ply[i].rnds)printf("%-5d", ply[i].rd[j]);
REP(j, 4 - ply[i].rnds)printf(" ");
printf("DQ\n"); i++; continue;
}
int j = i, bin = 0;
double tot = 0.0;
bool have_money = false;
while (j < cnt && ply[i].sc72 == ply[j].sc72) {
if (!ply[j].yu) {
bin++;
if (pos < maxp) {
tot += per[pos++];
have_money = true;
}
}
j++;
}
int place = i + 1, x = place, w = 0;
while (x) { w++; x /= 10; }
while (i < j) {
printf("%s %d", ply[i].name, place);
if (bin > 1 && have_money && !ply[i].yu) {
printf("T");
for (int k = w + 2; k <= 10; k++)printf(" ");
}
else for (int k = w + 1; k <= 10; k++)printf(" ");
REP(k, 4)printf("%-5d", ply[i].rd[k]);
if (have_money && !ply[i].yu) {
double amount = all * tot / bin;
printf("%-10d", ply[i].sc72);
printf("$%9.2lf\n", amount / 100.0);
}
else printf("%d\n", ply[i].sc72);
i++;
}
}
if (T)printf("\n");
}
return 0;
}
来源:CSDN
作者:Barsaker
链接:https://blog.csdn.net/TK_wang_/article/details/104728029