PAT (Advanced Level) Practice 1075 PAT Judge

一、概述

写一个模仿PAT的算法计算总分的程序。

挺麻烦的,和考场问题差不多。总分排序加上各人各题排序。

两个排序之后还有几个坑:

这样的人是不会输出的:没有过submit的人,sub了但是没有编译通过的人。

为了把这样的人摘出去,我们需要使用两个旗语,分别计算sub数和编译成功数。

都不为0才输出。

第二个坑是只要有sub,那么即使编译未通过,该题分数也是0而不是-,这一点要注意。

最后一个检查点有这样一个坑:如果之前编译通过了,之后编译未通过,那么分数不会变。虽然现实中出现这种蛋疼的概率很小,但还是要考虑。我就是没考虑这点,粗暴的遇到sub的-1就直接将该题分数改为0,因此最后一个检查点卡了一下。

二、分析

分别用两个结构体存储sub和user。如下:

struct submission
{
	int userID;
	int problemID;
	int partialscore;
}sub[100010];

struct User
{
	int s[5] = { -1,-1,-1,-1,-1 };
	int sum = 0;
	int perfect = 0;
	int subnum = 0;
	int passnum = 0;
	int final = 0;
	int userID;
}user[10010];

user的单项分数赋初值为-1有利于减少输出时的判断。

共需排序两次,一次是排序sub,按ID优先,题目其次,分数再其次排序;一次是排序user,按总分优先,完美数其次,id再其次排序。如下:

bool cmp(submission a, submission b)
{
	if (a.userID != b.userID)
		return a.userID < b.userID;
	else if (a.problemID != b.problemID)
		return a.problemID < b.problemID;
	else
		return a.partialscore > b.partialscore;
}
bool cmpfinal(User a, User b)
{
	if (a.sum != b.sum)
		return a.sum > b.sum;
	else if (a.perfect != b.perfect)
		return a.perfect > b.perfect;
	else
		return a.userID<b.userID;
}

先存储输入数据,然后进行第一次排序和处理。

sort(sub, sub + M, cmp);
for (i = 0; i < M; i++)
{
	if (sub[i].partialscore == -1 && user[sub[i].userID].s[sub[i].problemID - 1] == -1)//这里是最后一个检查点的坑
	{
		user[sub[i].userID].s[sub[i].problemID - 1] = 0;//sub的-1和位编译通过不一样
		user[sub[i].userID].subnum++;
	}
	if (sub[i].partialscore > user[sub[i].userID].s[sub[i].problemID - 1])
	{
		user[sub[i].userID].s[sub[i].problemID - 1] = sub[i].partialscore;
		user[sub[i].userID].subnum++;
		user[sub[i].userID].passnum++;
		if (user[sub[i].userID].s[sub[i].problemID - 1] == Smax[sub[i].problemID - 1])
			user[sub[i].userID].perfect++;
	}
}
for (i = 1; i < N + 1; i++)
{
	user[i].userID = i;
	for (j = 0; j < K; j++)
	{
		if (user[i].s[j] >= 0)
			user[i].sum += user[i].s[j];
	}
}

然后是第二次排序和排总名次。

sort(user + 1, user + N + 1, cmpfinal);
user[1].final = 1;
for (i = 2; i < N + 1; i++)
{
	if (user[i].sum == user[i - 1].sum)
		user[i].final = user[i - 1].final;
	else
		user[i].final = i;
}

最后输出即可。

三、总结

用了两个结构体之后代码有时候会变得好长,要注意分析。

PS:代码如下:

#include<stdio.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

struct submission
{
	int userID;
	int problemID;
	int partialscore;
}sub[100010];

struct User
{
	int s[5] = { -1,-1,-1,-1,-1 };
	int sum = 0;
	int perfect = 0;
	int subnum = 0;
	int passnum = 0;
	int final = 0;
	int userID;
}user[10010];

bool cmp(submission a, submission b)
{
	if (a.userID != b.userID)
		return a.userID < b.userID;
	else if (a.problemID != b.problemID)
		return a.problemID < b.problemID;
	else
		return a.partialscore > b.partialscore;
}
bool cmpfinal(User a, User b)
{
	if (a.sum != b.sum)
		return a.sum > b.sum;
	else if (a.perfect != b.perfect)
		return a.perfect > b.perfect;
	else
		return a.userID<b.userID;
}

int main()
{
	int N, K, M;//用户数,题目数,提交次数
	scanf("%d %d %d", &N, &K, &M);
	int Smax[5] = { 0 };
	int i, j;
	for (i = 0; i < K; i++)
		scanf("%d", &Smax[i]);
	for (i = 0; i < M; i++)
	{
		scanf("%d %d %d", &sub[i].userID, &sub[i].problemID, &sub[i].partialscore);
	}
	sort(sub, sub + M, cmp);
	for (i = 0; i < M; i++)
	{
		if (sub[i].partialscore == -1 && user[sub[i].userID].s[sub[i].problemID - 1] == -1)
		{
			user[sub[i].userID].s[sub[i].problemID - 1] = 0;
			user[sub[i].userID].subnum++;
		}
		if (sub[i].partialscore > user[sub[i].userID].s[sub[i].problemID - 1])
		{
			user[sub[i].userID].s[sub[i].problemID - 1] = sub[i].partialscore;
			user[sub[i].userID].subnum++;
			user[sub[i].userID].passnum++;
			if (user[sub[i].userID].s[sub[i].problemID - 1] == Smax[sub[i].problemID - 1])
				user[sub[i].userID].perfect++;
		}
	}
	for (i = 1; i < N + 1; i++)
	{
		user[i].userID = i;
		for (j = 0; j < K; j++)
		{
			if (user[i].s[j] >= 0)
				user[i].sum += user[i].s[j];
		}
	}
	sort(user + 1, user + N + 1, cmpfinal);
	user[1].final = 1;
	for (i = 2; i < N + 1; i++)
	{
		if (user[i].sum == user[i - 1].sum)
			user[i].final = user[i - 1].final;
		else
			user[i].final = i;
	}
	for (i = 1; i < N + 1; i++)
	{
		if (user[i].passnum != 0 && user[i].subnum != 0)
		{
			printf("%d %05d %d", user[i].final, user[i].userID, user[i].sum);
			for (j = 0; j < K; j++)
			{
				if (user[i].s[j] != -1)
					printf(" %d", user[i].s[j]);
				else
					printf(" -");
			}
			printf("\n");
		}
	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值