例题5-10 PGA巡回赛的奖金(PGA Tour Prize Money,ACM/ICPC World Finals 1990 UVa207)

原题链接: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;
}
发布了104 篇原创文章 · 获赞 97 · 访问量 4515

猜你喜欢

转载自blog.csdn.net/TK_wang_/article/details/104728029