1075. PAT Judge (25)

题目:

The ranklist of PAT is generated from the status list, which shows the scores of the submittions. This time you are supposed to generate the ranklist for PAT.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 positive integers, N (<=104), the total number of users, K (<=5), the total number of problems, and M (<=105), the total number of submittions. It is then assumed that the user id's are 5-digit numbers from 00001 to N, and the problem id's are from 1 to K. The next line contains K positive integers p[i] (i=1, ..., K), where p[i] corresponds to the full mark of the i-th problem. Then M lines follow, each gives the information of a submittion in the following format:

user_id problem_id partial_score_obtained

where partial_score_obtained is either -1 if the submittion cannot even pass the compiler, or is an integer in the range [0, p[problem_id]]. All the numbers in a line are separated by a space.

Output Specification:

For each test case, you are supposed to output the ranklist in the following format:

rank user_id total_score s[1] ... s[K]

where rank is calculated according to the total_score, and all the users with the same total_score obtain the same rank; and s[i] is the partial score obtained for the i-th problem. If a user has never submitted a solution for a problem, then "-" must be printed at the corresponding position. If a user has submitted several solutions to solve one problem, then the highest score will be counted.

The ranklist must be printed in non-decreasing order of the ranks. For those who have the same rank, users must be sorted in nonincreasing order according to the number of perfectly solved problems. And if there is still a tie, then they must be printed in increasing order of their id's. For those who has never submitted any solution that can pass the compiler, or has never submitted any solution, they must NOT be shown on the ranklist. It is guaranteed that at least one user can be shown on the ranklist.

Sample Input:
7 4 20
20 25 25 30
00002 2 12
00007 4 17
00005 1 19
00007 2 25
00005 1 20
00002 2 2
00005 1 15
00001 1 18
00004 3 25
00002 2 25
00005 3 22
00006 4 -1
00001 2 18
00002 1 20
00004 1 15
00002 4 18
00001 3 4
00001 4 2
00005 2 -1
00004 2 0
Sample Output:
1 00002 63 20 25 - 18
2 00005 42 20 0 22 -
2 00007 42 - 25 - 17
2 00001 42 18 18 4 2
5 00004 40 15 0 25 -
注意:
1、这道题目考察的还是分析能力,把所有的情况都分析清楚程序自然就很容易写出来了。
2、我的思路是每次输入一次提交记录的时候都来判断一次是否得了更高的分数,是则更新总分并判断是否得了满分,最后以总分、得满分题目的个数、id来排序并输出。
3、注意以下几种情况:
     1)如果本次提交得分为-1,也就是说未通过编译,并且当前user本题也是为通过编译或未提交过的状态,那么这时候要记得0分而不是依然记录为-1,题例中的00005 2 -1就是这样一个案例,但是需要注意的是这种情况并不改变当前用户是否要输出的状态,如果这个用户只提交过一次而且得分为-1,那么这个用户最后是不需要输出的。
     2)如果本次提交得分比记录中的得分要高,那么就需要更新得分,如果之前本题的得分-1,也就是说这是第一次通过编译并且得分,那么在更新total的时候的加数就是本次得分,而如果之前本题的得分不是-1,那么加数就是增长的分数值。
     3)注意输出的时候total=0也是需要输出的,total=0说明有提交且通过编译的problem,只是结果不正确得分为0而已。

代码:
//1075
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

struct user
{
	int id;
	int score[6];//score of each problem
	int total;//total score
	int solved;//number of solved problems
	bool operator > (const user &u)const
	{
		if(total!=u.total)
			return total>u.total;
		else if(solved!=u.solved)
			return solved>u.solved;
		else
			return id<u.id;
	}
};

int main()
{
	int n,k,m;
	scanf("%d%d%d",&n,&k,&m);
	int full[6];
	for(int i=1;i<=k;++i)
		scanf("%d",&full[i]);
	vector<user>usr;
	usr.resize(n+1);
	for(int i=0;i<n+1;++i)
	{
		usr[i].id=i;
		//score[i]=-1 means problem i has never been or submitted
		memset(usr[i].score,-1,sizeof(usr[i].score));
		usr[i].solved=0;
		//total=-1 means the user has never submitted any solution that 
		//can pass the compiler, or has never submitted any solution
		usr[i].total=-1;
	}
	for(int i=0;i<m;++i)
	{
		int id,problem,score;//user's id, problem id and score
		scanf("%d%d%d",&id,&problem,&score);
		if(score>usr[id].score[problem])
		{//refresh the score and the total score
			if(usr[id].total==-1)//first time to pass the compiler
				usr[id].total=score;
			else
			{
				if(usr[id].score[problem]==-1)//first time to pass this problem's compiler
					usr[id].total += score;
				else
					usr[id].total += score-usr[id].score[problem];
			}
			if(score==full[problem])
				++usr[id].solved;
			usr[id].score[problem]=score;
		}
		else if(score==-1 && usr[id].score[problem]==-1)
		{//first time to submit this problem but failed
			usr[id].score[problem]=0;
		}
	}
	sort(usr.begin(),usr.end(),greater<user>());
	int rank=1;
	for(int i=0;i<=n;++i)
	{
		if(usr[i].total==-1)
			break;
		if(i>0 && usr[i].total!=usr[i-1].total)
			rank=i+1;
		printf("%d %05d %d",rank,usr[i].id,usr[i].total);
		for(int j=1;j<=k;++j)
		{//print the score
			if(usr[i].score[j]!=-1)
				printf(" %d",usr[i].score[j]);
			else
				printf(" -");
		}
		printf("\n");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值