首页 > 试题广场 >

PAT Judge (25)

[编程题]PAT Judge (25)
  • 热度指数:5299 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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.


输出描述:
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.
示例1

输入

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

输出

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.不用判断分数是否会超过FullMark
2.如果学生A被输出,他曾提交过某题x,但是没通过即输入“A x -1”,x成绩输出为0
3.与上相对,如果学生A所有题都没通过过,但是曾经提交过-1,不被输出
4.按照总分递减、答对递减、ID递增的顺序排列,仅列出有成绩的学生(0 - - -也算,但是- - - -不算)
最后有一点我不是很理解的 如果加上ios::sync_with_stdio(false)会通不过答案 我本地没有异常找不到原因
大体思路:
Score[ID][problem]保存学生成绩
然后统计要被输出的学生的total_score和access_number
根据要求对学生排序
依次输出(稍微注意下rank的更新)
代码如下:
#include <iostream>
#include <memory.h>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef struct sStudent {
	int ID, Score, Access;
	sStudent(int id, int sc, int acc) :ID(id), Score(sc), Access(acc) {}
}Stu;

bool cmp(Stu s1, Stu s2) {
	if (s1.Score - s2.Score)return s1.Score > s2.Score;
	if (s1.Access - s2.Access)return s1.Access > s2.Access;
	return s1.ID < s2.ID;
}

int main(int argc, const char* argv[]) {
        //ios::sync_with_stdio(false);    加上就错了,不知道原因
	int N, K, M, FullMark[5];
	cin >> N >> K >> M;
	auto Score = new int[N][5];
	int* Complete = new int[N];
	memset(Complete, 0, sizeof(int) * N);
	for (int i = 0;i < N;i++)
		for (int j = 0;j < K;j++)Score[i][j] = -2;        
                //    为了区分没提交过和提交-1的
	for (int i = 0;i < K;i++)cin >> FullMark[i];
	int index, problem, score;
	while(M--) {
		cin >> index >> problem >> score;
		index--;problem--;
		if (Score[index][problem] < score)
			Score[index][problem] = score;        //    输入-1也会被记录
	}
	vector<Stu> stu;
	for (int i = 0;i < N;i++) {
		int total = 0;
		bool flag = false;
		for (int j = 0;j < K;j++) {
			if (Score[i][j] == FullMark[j])Complete[i]++;
			if (Score[i][j] >= 0) {
				total += Score[i][j];
				flag = true;                //    有成绩输入才会被输出
			}
		}
		if (flag)stu.push_back(Stu(i, total, Complete[i]));
	}
	sort(stu.begin(), stu.end(), cmp);                //    仅排序被输出的学生
	printf("1 %05d %d", stu[0].ID + 1, stu[0].Score);
	for (int j = 0;j < K;j++) {
		if (Score[stu[0].ID][j] >= 0)
			cout << " " << Score[stu[0].ID][j];
		else if (Score[stu[0].ID][j] == -1)cout << " 0";
		else cout << " -";
	}
	int rank = 1;
	for (int i = 1;i < stu.size();i++) {
		if (stu[i].Score < stu[i - 1].Score)rank = i + 1;    //    成绩不同才更新
		printf("\n%d %05d %d", rank, stu[i].ID + 1, stu[i].Score);
		for (int j = 0;j < K;j++) {
			if (Score[stu[i].ID][j] >= 0)
				cout << " " << Score[stu[i].ID][j];
			else if (Score[stu[i].ID][j] == -1)cout << " 0";
			else cout << " -";
		}
	}

	delete[] Complete;
	delete[] Score;
	//system("pause");
	return 0;
}

发表于 2017-02-06 18:04:59 回复(1)

这题主要是注意细节:

  • 只有提交过题目并且通过编译的用户才显示在排行榜上
  • 提交过但没有通过编译的题目打印“0”,而没有提交过的题目打印“-”
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;

int n, k, m;
int p[6];

struct user {
  int id, rank;
  bool show = false;
  int total_score;
  int p[6] = {-1, -1, -1, -1, -1, -1};  // -1 means never submitted
  int perfect;
} users[10000 + 5];

bool cmp(const user u1, const user u2) {
  if (u1.total_score == u2.total_score) {
    if (u1.perfect == u2.perfect) {
      return u1.id < u2.id;
    }
    return u1.perfect > u2.perfect;
  }
  return u1.total_score > u2.total_score;
}

int main() {
  scanf("%d%d%d", &n, &k, &m);
  for (int i = 1; i <= k; i++) {
    scanf("%d", &p[i]);
  }
  int id, p_id, p_score;
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d", &id, &p_id, &p_score);
    users[id].id = id;
    // once submitted set the score to 0
    if (users[id].p[p_id] == -1) users[id].p[p_id] = 0;
    // track the highest score
    if (users[id].p[p_id] < p_score) users[id].p[p_id] = p_score;
    if (p_score != -1) users[id].show = true;
  }
  // caculate total score
  for (int i = 1; i <= n; i++) {
    if (users[i].show) {
      for (int j = 1; j <= k; j++) {
        int s = users[i].p[j];
        if (s == p[j]) users[i].perfect++;
        if (s != -1) users[i].total_score += s;
      }
    }
  }
  sort(users + 1, users + n + 1, cmp);
  int rank = 1;
  user *last_user = NULL;
  for (int i = 1; i <= n; i++) {
    if (users[i].show) {
      if (last_user != NULL && users[i].total_score == last_user->total_score) {
        printf("%d %05d %d", last_user->rank, users[i].id,
               users[i].total_score);
        users[i].rank = last_user->rank;
      } else {
        printf("%d %05d %d", rank, users[i].id, users[i].total_score);
        users[i].rank = rank;
      }
      rank++;
      last_user = &users[i];
      for (int j = 1; j <= k; j++) {
        if (users[i].p[j] == -1) {
          printf(" -");
        } else {
          printf(" %d", users[i].p[j]);
        }
      }
      printf("\n");
    }
  }

  return 0;
}
发表于 2019-04-24 13:49:05 回复(0)
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;

int N, K, M, p[10];
typedef struct Stu {
    string id;
    int rank, s[10], n_fm, sum_s;
    Stu(string _id) :id(_id), sum_s(0), n_fm(0), rank(0) {
        for (int i = 1; i <= K; ++i)s[i] = -2;
    }
    bool be_shown() {
        for (int i = 1; i <= K; ++i)if (s[i] >= 0)return true;
        return false;
    }
    bool operator < (const Stu& s)const {
        if (sum_s > s.sum_s)return true;
        else if (sum_s == s.sum_s) 
            if (n_fm > s.n_fm)return true;
            else if (n_fm == s.n_fm) 
                return id < s.id;
        return false;
    }
    void printStu() const {
        cout << rank << " " << id << " " << sum_s << " ";
        for (int i = 1; i <= K; ++i) {
            if (s[i] == -1)cout << 0;
            else if (s[i] == -2)cout << "-";
            else cout << s[i];
            if (i < K)cout << " ";
        }
    }
    void update_ans(int i, int ps) { if (s[i] < ps) s[i] = ps; }
    void cnt_sum() { for (int j = 1; j <= K; ++j)if (s[j] > 0)sum_s += s[j]; }
    void cnt_fm() { for (int j = 1; j <= K; ++j) if (s[j] == p[j])++n_fm; }
}Stu;
map<string, int> stu_map; vector<Stu> stu;//一个很重要的映射技巧

int main()
{
    cin >> N >> K >> M; string uid; int pro_id, ps;
    for (int i = 1; i <= K; ++i)cin >> p[i];
    for (int i = 1; i <= M; ++i) {
        cin >> uid >> pro_id >> ps;
        if (stu_map.find(uid)==stu_map.end()) {//初次创建学生,交叉映射
            stu_map[uid] = (int)stu.size();
            stu.push_back(Stu(uid));
        }
        stu[stu_map[uid]].update_ans(pro_id, ps);
    }

    for (auto it = stu.begin(); it != stu.end(); ) {
        (*it).cnt_sum(); (*it).cnt_fm();
        if (!it->be_shown())it = stu.erase(it);
        else ++it;
    }
    sort(stu.begin(), stu.end());
    int len = (int)stu.size(), Rank = 1; 
    for (int i = 0; i < len; ++i) {
        if (i && stu[i].sum_s < stu[i - 1].sum_s)Rank = i + 1;
        stu[i].rank = Rank;
        stu[i].printStu(); if (i < len - 1)cout << endl;
    }
    return 0;
}

发表于 2021-03-05 12:41:28 回复(0)
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 10001;
const int maxp = 6;
int p[maxp];
bool visit[maxn] = {false};
struct User {
    int id, total_score, full_mark_num;
    int score[maxp];
    int isPass;
};
User users[maxn];
void init() {
    for(int i=1; i<maxn; i++) {
        users[i].id = i;
        users[i].total_score = 0;
        users[i].full_mark_num = 0;
        users[i].isPass = 0;
        for(int j=1; j<maxp; j++) {
            users[i].score[j] = -2;
        }
    }
}

bool cmp(User a, User b) {
    if(a.isPass == 1 && b.isPass == 1) {
        if(a.total_score != b.total_score) {
            return a.total_score>b.total_score;
        } else {
            if(a.full_mark_num != b.full_mark_num) {
                return a.full_mark_num > b.full_mark_num;
            } else {
                return a.id < b.id;
            }
        }
    } else {
        return a.isPass > b.isPass;
    }
}
int main() {
    int n, k, m;
    init();
    scanf("%d %d %d", &n, &k, &m);
    for(int i=1; i<=k; i++) {
        scanf("%d", p+i);
    }
    for(int i=1; i<=m; i++) {
        int p_id, p_score, id;
        scanf("%d %d %d", &id, &p_id, &p_score);
        if(p_score != -1) {
            users[id].isPass = 1;
            if(p_score == p[p_id] && users[id].score[p_id] != p[p_id]) {
                users[id].full_mark_num++;
            }
            if(p_score > users[id].score[p_id]) {
                if(users[id].score[p_id] <=0 ) {
                    users[id].total_score += p_score;
                } else {
                    users[id].total_score += (p_score - users[id].score[p_id]);
                }
                users[id].score[p_id] = p_score;
            }
        } else {
            if(users[id].score[p_id] == -2 )
                users[id].score[p_id] = 0;
        }
    }
    sort(users+1, users+1+n, cmp);
    int prev_score = users[1].total_score;
    for(int i=1,u_rank=1; i<=n; i++) {
        if(users[i].isPass == 0)
            break;
        if(users[i].total_score == prev_score)
            printf("%d", u_rank);
        else{
            printf("%d", i);
            u_rank = i;
            prev_score = users[i].total_score;
        }
        printf(" %05d %d ", users[i].id, users[i].total_score);
        for(int j=1; j<k; j++) {
            if(users[i].score[j] == -2)
                printf("- ");
            else
                printf("%d ",users[i].score[j]);
        }

        if(users[i].score[k] == -2)
            printf("-\n");
        else
            printf("%d\n",users[i].score[k]);
    }

}

发表于 2019-09-12 16:48:39 回复(0)
思路:关键是
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.
对于那些 从未解决过任何问题或者是从未提交过代码的人他们不会显示在排行榜上。
其实对于
00006 4 0 这种类型的该部该显示呢??  应该这种条件应该是可以通过一小部分的条件但是不能
最小分数的阈值。所以 也应该显示出来。
有的时候这中一下子一大堆测试样例,但是很难从结果看自己是否正确只能从别人做出来的答案中推出
自己的逻辑问题。心好累
还有代码如果写太长,不是说不好,只是很容易错。 好的代码永远是简洁的,但不会太简介,
这样就违背了算法的可读性。
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#include <iomanip>
using namespace std;

/*7 4 20
20 25 25 30
00002 2 12*/

#ifndef debug
ifstream ifile("case.txt");
#define cin ifile
#endif

struct stu
{
    int id;
    int totalScore = 0;
    map<int,int> scores;
    int prefectNum = 0;
    bool submit = false;
};

bool Cmp(struct stu & a, struct stu & b)
{
    if (a.totalScore != b.totalScore)
    {
        return a.totalScore > b.totalScore;
    }
    else if (a.prefectNum != b.prefectNum)
    {
        return a.prefectNum > b.prefectNum;
    }
    else
        return a.id < b.id;
}


int main()
{
    int n, k, s;
    while (cin >> n >> k >> s)
    {
        vector<int> allscores(k);
        vector<struct stu> students(n);
        // 初始化id
        for (int i = 0; i < n; i++)
        {
            students[i].id = i+1;
            for (int j = 0; j < k; j++)
            {
                students[i].scores[j + 1] = -2;
            }
        }
        for (int i = 0; i < k; i++)
        {
            cin >> allscores[i];
        }

        int id, problem, score;
        for (int i = 0; i < s; i++)
        {
            cin >> id >> problem >> score;
            if (score >= students[id - 1].scores[problem])
            {
                if(score >= 0)
                    students[id - 1].submit = true;
                students[id - 1].scores[problem] = score;
            }
            
        }
        // 计算总分
        for (int i = 0; i < n; i++)
        {
            for (auto it = students[i].scores.begin(); it != students[i].scores.end(); it++)
            {
                if(it->second >= 0)
                    students[i].totalScore += it->second;
                if (allscores[it->first-1] == it->second)
                {
                    students[i].prefectNum++;
                }
            }
        }
        
        // 排名
        sort(students.begin(), students.end(), Cmp);
        int rank = 1;
        int coutNum = 0;
        int lastSCore = 0;
    
        for(int i = 0; i<n; i++)
        {
            if (students[i].totalScore == 0)
            {
                if (!students[i].submit)
                {
                    continue;
                }
            }
            coutNum++;
            if (i != 0 && students[i].totalScore != lastSCore)
            {
                rank = coutNum;
            }
            cout << rank << " ";
            cout << setfill('0') << setw(5) << students[i].id << " ";
            cout << students[i].totalScore;
            for (int j = 1; j <= k; j++)
            {
                if (students[i].scores[j] != -2)
                {
                    cout << " " << (students[i].scores[j] == -1 ? 0 : students[i].scores[j]);
                }
                else
                {
                    cout << " -";
                }
            }
            lastSCore = students[i].totalScore;
            cout << endl;
        }
    }
    system("pause");
}  

发表于 2018-08-28 20:11:02 回复(0)
有一个地方在题目里没有明确指出但是观察样例可以发现:
如果某次提交分数为-1(编译不通过)则相应的分数状态不是 - 而是0分
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 10000, K = 5, M = 100000;
int n, m, k;
int p[K];
struct User {
    int s[K];
    int total, solved, active;
    User()
    {
        total = solved = active = 0;
        memset(s, -1, sizeof(s));
    }
    void Update(int pi, int score)
    {
        if(score == -1)
            score = 0;
        else
            active = 1;
        if(score > s[pi]) {
            total += s[pi] == -1 ? score : score - s[pi];
            s[pi] = score;
            solved += s[pi] == p[pi] ? 1 : 0;
        }
    }
    void Print(int rank, int uid) const
    {
        if(!active)
            return;
        printf("%d %05d %d", rank, uid, total);
        for(int i = 0; i < k; i++) {
            if(s[i] != -1)
                printf(" %d", s[i]);
            else
                printf(" -");
        }
        printf("\n");
    }
};
User u[N];
int idx[N];
bool Comp(int a, int b) //index a,b
{
    const User &l = u[a];
    const User &r = u[b];
    if(l.total > r.total || (l.total == r.total && l.solved > r.solved) ||\
       (l.total == r.total && l.solved == r.solved && a < b))
        return true;
    return false;
}
int main()
{
    scanf("%d%d%d\n", &n, &k, &m);
    for(int i = 0; i < n; i++) {
        idx[i] = i;
    }
    for(int i = 0; i < k; i++)
        scanf("%d", &p[i]);
    for(int i = 0; i < m; i++) {
        int ui, pi, score;
        scanf("%d%d%d", &ui, &pi, &score);
        ui--; pi--;
        u[ui].Update(pi, score);
    }
    sort(idx, idx + n, Comp);
    int rank = 0;
    u[idx[0]].Print(rank + 1, idx[0] + 1);
    for(int i = 1; i < n; i++) {
        if(u[idx[i-1]].total!=u[idx[i]].total)
            rank = i;
        u[idx[i]].Print(rank + 1, idx[i] + 1);
    }
    return 0;
}

发表于 2017-07-25 15:23:39 回复(0)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N=10000,M=100000;
int n,m,k,p[5];

struct Stu{     int score[5];     int total, solved, active;     Stu(){         total = solved = active = 0;         memset(score, -1, sizeof(score));     }     void Update(int t, int s)     {         if(s == -1)             s = 0;         else             active = 1;         if(s > score[t])         {             total += (score[t]==-1?s:s-score[t]);             score[t] = s;             solved += (score[t]==p[t]?1:0);         }     }     void Print(int rank, int id)     {         if(!active)             return;         printf("%d %05d %d", rank, id, total);         for(int i=0;i<k;i++)         {             if(score[i] != -1)                 printf(" %d", score[i]);             else                 printf(" -");         }         printf("\n");     }
};

Stu stu[N];
int idx[N];

bool cmp(int a, int b)
{     const Stu &S1 = stu[a];     const Stu &S2 = stu[b];     if(S1.total > S2.total)         return true;     else if(S1.total==S2.total && S1.solved>S2.solved)         return true;     else if(S1.total==S2.total && S1.solved==S2.solved && a<b)         return true;     else         return false;
}

int main()
{     cin>>n>>k>>m;     for(int i=0;i<n;i++)         idx[i] = i;     for(int i=0;i<k;i++)         cin>>p[i];     for(int i=0;i<m;i++)     {         int ui,pi,s;         cin>>ui>>pi>>s;         ui--;         pi--;         stu[ui].Update(pi, s);     }     sort(idx, idx+n, cmp);     int rank=0;     stu[idx[0]].Print(rank+1, idx[0]+1);     for(int i=1;i<n;i++)     {         if(stu[idx[i-1]].total != stu[idx[i]].total)             rank = i;         stu[idx[i]].Print(rank+1, idx[i]+1);     }     return 0;
}

发表于 2018-03-08 01:32:51 回复(0)
#include <bits/stdc++.h>
using namespace std;
struct user{
    int id, score_total, perfect_num;
    int score[6];
    bool perfect[6];
    bool enable;//能否上榜
    user() {
        id = -1;
        score_total = 0;
        perfect_num = 0;
        enable = false;
        for(int i=0;i<6;++i){
            score[i] = -2;
            perfect[i] = true;
        }
    }
};

bool cmp(user a, user b){
    if(a.enable!=b.enable) return  a.enable>b.enable;
    else if(a.score_total!=b.score_total) return a.score_total>b.score_total;
    else if(a.perfect_num!=b.perfect_num) return a.perfect_num>b.perfect_num;
    else return a.id<b.id;
}
user all[10005];
int full_mark[6];
int main() {
    int N, K, M;
    scanf("%d %d %d", &N, &K, &M);
    for(int i=1;i<=K;++i){
        scanf("%d", &full_mark[i]);
    }
    for(int i=0;i<M;++i){
        int curr_id, curr_prob, curr_score;
        scanf("%d %d %d", &curr_id, &curr_prob, &curr_score);
        all[curr_id].id = curr_id;
        if(curr_score!=-1){//提交通过
            all[curr_id].enable = true;
            if(all[curr_id].score[curr_prob]<0){//第一次通过则全加刷新
                all[curr_id].score_total += curr_score;
                all[curr_id].score[curr_prob] = curr_score;
            }else{//之前已得过分
                all[curr_id].score_total += curr_score<all[curr_id].score[curr_prob]?0:curr_score-all[curr_id].score[curr_prob];
                all[curr_id].score[curr_prob] = max(curr_score, all[curr_id].score[curr_prob]);
            }

            if(curr_score==full_mark[curr_prob]&&all[curr_id].perfect[curr_prob]){//满分且该题第一次满分
                all[curr_id].perfect_num++;
                all[curr_id].perfect[curr_prob] = false;
            }
        }
        else{
            all[curr_id].score[curr_prob] = -1;
        }
    }
    sort(all, all+N+10, cmp);

    int Rank = 1, last_score = all[0].score_total, score_equal = 0;
    for(int i=0;i<=N;++i){
        if(all[i].id>0&&all[i].enable){
            if(all[i].score_total<last_score) {
                Rank += score_equal;
                score_equal = 1;
            }
            else if(all[i].score_total==last_score) score_equal++;
            printf("%d ", Rank);
            last_score = all[i].score_total;
            printf("%05d %d", all[i].id, all[i].score_total);
            for(int j=1;j<=K;++j){
                if(all[i].score[j]==-1){
                    printf(" 0");
                }else if(all[i].score[j]==-2){//
                    printf(" -");
                }
                else{
                    printf(" %d", all[i].score[j]);
                }
            }
            printf("\n");
        }
    }
    return 0;
}
PAT没问题牛客全错是什么鬼,给的测试样例输出都一样啊
发表于 2020-07-22 13:45:24 回复(0)

	
//最大坑点:如果学生A提交过某题x,但是没通过即输入“A x -1”,那么对应题目x的成绩输出为0而不是'-',因此isSubmit[maxn][6]用来判断每个题是否提交,因为最后输出的时候如果某道题得分为0的话,需要是得分为0(无论通没通过编译器,如第一条所说,能显示的人某道题没通过编译器则输出为0而不是‘-’)还是没有提交为0,前者输出0,后者输出‘-’。
//得的分为-1只是代表未通过编译,只是一个标记,实际上并不会减去一分 //坑点,一个学生可能会重复提交已经AC的代码,在这里,最开始我们判断了重复提交的时候,如果分数更高则会更改分数,但是ac的个数如果不判断,可能会出错,因此还需要加一个isAc[maxn][6]来标记是否该题已经ac过 #include<iostream> #include<vector> #include<limits.h> #include<queue> #include<algorithm> using namespace std; struct person {  int score;  int ac;  int id;  person(int score, int ac, int id) :score(score), ac(ac), id(id) {} }; const int MAXN = 10005; bool cmp(person a, person b) {  if (a.score != b.score) { return a.score > b.score; }  else if (a.score == b.score & a.ac != b.ac) { return a.ac > b.ac; }  else { return a.id < b.id; } } int main() {  int n, k, num, x;  cin >> n >> k >> num;  int full_marks[6] = { 0 };  int each_score[MAXN][6] = { {0} };  bool isSubmit[MAXN][6] = { {false} };  bool isAc[MAXN][6] = { {false } };  bool flag[MAXN] = { false };//记录是否需要显示出来  int ac[MAXN] = { 0 };  for (int i = 1; i <= k; i++) {   cin >> full_marks[i];  }  for (int i = 0; i < num; i++) {   int person_id, problem_id, score;   cin >> person_id >> problem_id >> score;   isSubmit[person_id][problem_id] = true;   if (score != -1) {    if (score > each_score[person_id][problem_id]) {     each_score[person_id][problem_id] = score;    }    if (score == full_marks[problem_id]&&!isAc[person_id][problem_id]) {     ac[person_id]++;     isAc[person_id][problem_id] = true;    }    flag[person_id] = true;   }  }  vector<person>priority;  for (int i = 1; i <= n; i++) {   if (flag[i]) {    int sum = 0;    for (int j = 1; j <= k; j++) {     sum += each_score[i][j];    }    priority.push_back(person(sum, ac[i], i));   }  }  sort(priority.begin(), priority.end(), cmp);  int rank = 1;  int cnt = 0;  for (int i = 0; i < priority.size(); i++) {   if (i && priority[i].score != priority[i - 1].score) {    rank += cnt;    cnt = 1;   }   else {    cnt++;   }   printf("%d %05d %d", rank, priority[i].id, priority[i].score);   for (int j = 1; j <= k; j++) {    if (each_score[priority[i].id][j]) { printf(" %d", each_score[priority[i].id][j]); }    else if (isSubmit[priority[i].id][j]) { printf(" 0"); }    else { printf(" -"); }   }   cout << '\n';  } }


编辑于 2020-05-16 11:18:50 回复(0)
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>
#include <vector>
#include <map>
#include <iomanip>
#include <sstream>
using namespace std;

//1075 PAT Judge
//过了PAT测试点
//按人,题号,排序。
//同人同题去重,取最高小分的一条记录
//pid从1开始编号。uid从1开始编号。
//
//本来猜的是过滤0分选手。后来发现......
//只要有过提交,且编译通过,哪怕没得分,类似于00001,1,0。虽然这题得分零,且只做了一题0,-,-,-。
//这个人也得显示。
//而提交过的,但是编译没通过的,最后-1,-,-,-。这样就得过滤,比如case中的6号选手。
//总结一下就是,在记分问题上,有过提交记录,该题就不能给'-'分,最低给0分。
//在显示问题上,有提交记录且编译通过,就得显示出来,否则不显示。
//边界人群为,有提交记录,但是没编译通过,这种人,记分需要记0分,显示又不能给显示。
//边界条件真难猜。

class stu {
public:
    int uid;
    bool show;
    int total,perfect;
    vector<int> s;

    stu() :uid(0),show(0),total(0), perfect(0),s(6, -2) {} //初始化为-2,方便检测这人有没有填过成绩。
};


int p[10];
stu users[10002];

bool cmp(stu a, stu b){    
    if(a.total!=b.total) return a.total > b.total; 
    else if (a.perfect != b.perfect) return a.perfect > b.perfect;
    else return a.uid < b.uid;
}

int main() {
    int n, k, m;
    cin >> n >> k >> m;
    for (int i = 1; i <= k; ++i) { cin >> p[i]; } //初始化满分
    for (int i = 1; i <= n; ++i) { users[i].uid=i; }//初始化序号
    int uid, pid, pscore;
    for (int i = 0; i < m; ++i) {
        scanf("%d%d%d", &uid, &pid, &pscore);
        //更新小分,这样可以保证-1分的提交也记录到
        if (pscore > users[uid].s[pid]) {
            users[uid].s[pid] = pscore;
            if (pscore == p[pid]) users[uid].perfect++;
        }
    }

    //统计总分
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= k; ++j) {
            
            if (users[i].s[j] >=0) {
                users[i].show = true;
                users[i].total += users[i].s[j];
            }
            else if (users[i].s[j] == -1) {
                //有过提交记录,但是没过编译的人才会拿到-1分
                //将他的这题分数置为0,这关系到pat.0,pat.1
                //但是这条提交不影响最后是否show。
                users[i].s[j] = 0;
            }
        }
    }
    //排序
    sort(users+1, users+1+n,cmp);

    //输出排名
    int last_rank = 0, last_total = 1000;
    int this_rank;
    for (int i = 1; i <= n; ++i) {

        if (!users[i].show) continue;

        if (users[i].total == last_total) this_rank = last_rank;
        else this_rank = i;


        cout << this_rank << " " << setfill('0') << setw(5) << users[i].uid << " " << users[i].total;

        //小分
        for (int j = 1; j <= k; ++j) {
            if (users[i].s[j] == -2)cout << " -";
            else cout << " " << users[i].s[j];
        }
        //换行
        cout << endl;

        last_rank = this_rank;
        last_total = users[i].total;
    }
    return 0;
}
编辑于 2020-02-29 16:03:43 回复(3)
使用面向对象的风格来写,不追求代码简短,但求思路清晰,修改简单快速。
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<vector>
#include<algorithm>
using namespace std;
int playerNum;
int problemNum;
int fullScore[10];	//0不计

class Player{
	static int rank;		//输出时的排名
	static int lastRank;	//上一个输出的排名
	static int lastSum;		//上次输出时的分数
public:
	int id;
	int score[6];	//成绩,0不计
	int isSlove[6];	//是否已解决第几问
	int sum;
	int perfect;	//满分题数
	int slove;		//通过题数
	//初始化数值
	void init(int nid){
		id = nid;
		slove = perfect = sum = 0;
		for (int i = 1; i <= problemNum; i++){
			score[i] = -99999;
			isSlove[i] = false;
		}
		return;
	}
	//输入成绩
	void inPutSorce(int pid, int newScore){
		if (score[pid] < newScore) {
			score[pid] = newScore;
		}
		return;
	}
	//计算或更新总分、满分题数、通过题数
	void update(){
		sum = 0;
		for (int i = 1; i <= problemNum; i++){
			if(score[i]>0)sum += score[i];
			if (score[i] == fullScore[i]) perfect++;
			if (score[i] >= 0) slove++;
		}
		if (slove == 0) {
			sum = -10000;
		}
	}
	//输出排名或成绩
	void printMsg(){
		if (slove==0) return;
		rank++;
		if (lastSum == sum){//成绩并列
			printf("%d %05d %d", lastRank, id, sum);
		}
		else{//排名数变动
			printf("%d %05d %d", rank, id, sum);
			lastRank = rank;
		}
		lastSum = sum;
		for (int i = 1; i <= problemNum; i++) {
			if (score[i] >= 0) printf(" %d", score[i]);
			else if (score[i] == -1) printf(" 0");
			else printf(" -");
		}
		printf("\n");
	}
	
	//排序依据,需要先使用update更新sum等数值
	bool operator < (const Player& p){
		if (sum != p.sum) return sum > p.sum;
		if (perfect != p.perfect) return perfect > p.perfect;
		return id < p.id;
	}
	
};

int Player::rank = 0;
int Player::lastRank = 0;
int Player::lastSum = 0;

int main(){
	int row;
	scanf("%d %d %d", &playerNum, &problemNum, &row);
	for (int i = 1; i <= problemNum; i++){
		scanf("%d", &fullScore[i]);
	}
	//创建内存并初始化
	Player *player = new(Player[playerNum+2]);	//0弃用
	for (int i = 1; i <= playerNum; i++) {
		player[i].init(i);
	}
	//获取成绩输入
	for (int i = 1; i <= row; i++){
		int id, pid, res;
		scanf("%d %d %d", &id, &pid, &res);
		player[id].inPutSorce(pid, res);
	}
	//计算总分、完美提交次数
	for (int i = 1; i <= playerNum; i++) {
		player[i].update();
	}
	//排序和输出结果
	sort(player+1, player + playerNum + 1);
	for (int i = 1; i <= playerNum; i++){
		player[i].printMsg();
	}
	return 0;
}
/*错误或不足记录:
1. 没有认真核对样例数据的输出与答案,导致没发现一处0输出了-,(编译不通的选手输出0分而非-)
2. 成绩输入存在-1值,所以默认值不应该为-1,否则状态存在二义性。
3. 6号选手一题编译错,不显示在排名表上, 5号选手某题始终未编译通过,但是显示结果为0,这里解析了一个不易发现的易错点:
至少一题成绩非-1才显示在排名榜上,在排名榜上的选手成绩,0 分为0分或-1,‘-’必定是未提交过的。
*/

发表于 2020-02-20 11:27:40 回复(0)
n,k,m = map(int,input().split())
kmark = list(map(int,input().split()))
lst = []
user = [[None for j in range(k)] for i in range(10001)]
for i in range(m):
    tem = list(map(int,input().split()))
    if tem[2]!=-1 and (user[tem[0]][tem[1]-1]==None or user[tem[0]][tem[1]-1]<=tem[2]):
        user[tem[0]][tem[1]-1] = tem[2]
    elif tem[2]==-1 and user[tem[0]][tem[1]-1]==None:#注意原来输入了-1 后来输入了0 要由0.0更新为0
        user[tem[0]][tem[1]-1] = 0.0
selected = []
for i in range(0,len(user)):
    for j in user[i]:
        if isinstance(j, int):     
            selected.append([i,0]+user[i])
            break
for i in range(0,len(selected)):
    tcon = 0
    for j in range(2,len(selected[i])):
        if selected[i][j]==kmark[j-2]:
            tcon+=1
    selected[i] = selected[i]+[tcon]
for i in selected:
    for j in range(2,len(i)-1):
        if i[j]!=None:
            i[1]+=i[j]
        else:
            i[j] = '-'
selected.sort(key = lambda x:(-x[1],-x[k+2],x[0]))
selected[0][0] = '%05d'%selected[0][0]
selected[0].pop()
for j in range(1,len(selected[0])):
    if isinstance(selected[0][j],float):
        selected[0][j] = int(selected[0][j])
print(1,' '.join(map(str,selected[0])))
con1,con2,st = 1,1,selected[0][1]
for i in range(1,len(selected)):
    if selected[i][1]!=st:
        con1+=con2
        con2=1
        st = selected[i][1]
    else:
        con2+=1
    selected[i][0] = '%05d'%selected[i][0]
    selected[i].pop()
    for j in range(1,len(selected[i])):
        if isinstance(selected[i][j],float):
            selected[i][j] = int(selected[i][j])
    print(con1,' '.join(map(str,selected[i])))
这道题有几点要注意:
1,输入为0 -1 -1 -1,-,-.....时 是可以有输出的,但是输入为-1,-,-,-1,-...时是没有输出的
2,如果有可以被输出的输入量,则输入-1对应的输出为0
3,仅列出有成绩的学生
4,排序为总分递减,全对的题目数递减和ID递增顺序输出。。。
发表于 2018-12-09 21:00:48 回复(0)
N,K,M=map(int,input().split())
score=list(map(int,input().split()))
student=[[i,None,0]+['-']*K for i in range(N+1)]
from functools import cmp_to_key
def cmp(a,b):
    if a[1]==b[1]:
        return b[2]-a[2] if a[2]!=b[2] else a[0]-b[0]
    else:
        return b[1]-a[1]
for i in range(M):
    a,b,c=map(int,input().split())
    if c==-1:
        student[a][b+2]=0 if student[a][b+2]=='-' else student[a][b+2]
    elif student[a][b+2]=='-' or student[a][b+2]<c or (student[a][b+2]==0 and c==0):
        d=c-student[a][b+2] if student[a][b+2]!='-' else c
        student[a][b+2]=c
        student[a][1]=student[a][1]+d if student[a][1] else d
        student[a][2]+=1 if score[b-1]<=c else 0
L=sorted(filter(lambda x:x[1]!=None ,student),key=cmp_to_key(cmp))
L.append([None,-1,None])
rank,tmp=1,[]
for i in range(len(L)):
    if i-1>=0 and L[i][1]==L[i-1][1]:
        tmp.append(i)
    else:
        for e in tmp:
            print('{} {:05d} {} '.format(rank,L[e][0],L[e][1])+' '.join(map(str,L[e][3:])))
        rank,tmp=rank+len(tmp),[I]
谜一样的题目
编辑于 2018-09-01 18:40:16 回复(0)
#include<iostream>
#include<vector>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std;

class tot_scor_id
{
public:
    int id;
    int perfe_num;
    int total_score;
};

bool cmp(tot_scor_id a, tot_scor_id b)
{
    if(b.total_score != a.total_score)
        return b.total_score < a.total_score;
    else if(b.perfe_num != a.perfe_num)
        return b.perfe_num < a.perfe_num;
    else
        return b.id > a.id;
}

int main()
{
    int N, K, M;                                            //总人数、总问题数、总提交数
    cin >> N >> K >> M;

    vector<int> Full_Score(K+1, 0);                            //每一题的满分
    for(int i = 1; i <= K; i++)
        cin >> Full_Score[i];

    vector<vector<int>> anwser(N+2, vector<int>(K+2, -2));
    int id_num, ques_num, score;
    for(int i = 1; i <= M; i++)
    {
        cin >> id_num >> ques_num >> score;
        anwser[id_num][ques_num] = max(anwser[id_num][ques_num], score);
    }

    vector<int> tot_score(N+1, 0);                            //每个同学的总分
    vector<int> perfect_finsh(N+1, 0);                        //每个同学 得满分的题目数
    vector<bool> jue(N+1, false);
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= K; j++)
        {
            if(anwser[i][j] >= 0)
            {
                tot_score[i] += anwser[i][j];
                jue[i] = true;
            }
            if(anwser[i][j] == Full_Score[j])
                perfect_finsh[i]++;
        }

    tot_scor_id rank[10002] = {0};
    int num = 1;
    for(int i = 1; i <= N; i++)
    {
        if(jue[i])
        {
            tot_scor_id stu;
            stu.id = i;
            stu.perfe_num = perfect_finsh[i];
            stu.total_score = tot_score[i];
            rank[num++] = stu;
        }
    }
    sort(rank+1, rank+num, cmp);
    
    //输出
    int rang_nu = 1;
    num = 1;
    for(int i = 1; i <= N; i++)
    {
        if(jue[rank[num].id] == false)
            break;
        if(tot_score[rank[num].id] != tot_score[rank[num-1].id] && i != 1)
            rang_nu = num;
        cout << rang_nu << " " << setw(5) << setfill('0') << rank[num].id << " " << tot_score[rank[num].id];
        for(int j = 1; j <= K; j++)
        {
            cout << " ";
            if(anwser[rank[num].id][j] == -2)
                cout << "-";
            else if(anwser[rank[num].id][j] == -1)
                cout << 0;
            else
                cout << anwser[rank[num].id][j];
        }
        num++;
        cout << endl;
    }
    system("pause");
    return 0;
}
发表于 2018-03-01 19:50:58 回复(0)
#include <iostream>
#include <cstdio>
#include <algorithm>
int p[6];
struct U {
    int numb,flag,total,rrank,perfect,score[6];
};
U user[10005];
bool cmp(U a,U b) {
    if(a.total != b.total)
        return a.total > b.total;
    else if(a.perfect != b.perfect)
        return a.perfect > b.perfect;
    else
        return a.numb < b.numb;
}
int main()
{
    int n,k,m;
    scanf("%d %d %d",&n,&k,&m);
    int nn,pn,ps;
    for(int i = 1;i <= k;i++)
        scanf("%d",&p[i]);
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= k;j++)
            user[i].score[j] = -2;
    for(int i = 1;i <= m;i++) {
        scanf("%d %d %d",&nn,&pn,&ps);
        user[nn].numb = nn;
        if(ps != -1)
            user[nn].flag = 1;
        user[nn].score[pn] = std::max(ps,user[nn].score[pn]);
    }
    for(int i = 1;i <= n;i++)
    for(int j = 1;j <= k;j++) {
        if(user[i].score[j] > 0)
            user[i].total += user[i].score[j];
        if(user[i].score[j] == p[j])
            user[i].perfect++;
    }
    std::sort(user+1,user+1+n,cmp);
    for(int i = 1;i <= n;i++) {
        user[i].rrank = i;
        if(i!=1 && user[i].total==user[i-1].total)
            user[i].rrank = user[i-1].rrank;
        if(user[i].flag == 0)
            continue;
        printf("%d %05d %d",user[i].rrank,user[i].numb,user[i].total);
        for(int j = 1;j <= k;j++) {
            if(user[i].score[j] == -2)
                printf(" -");
            else if(user[i].score[j] > 0)
                printf(" %d",user[i].score[j]);
            else
                printf(" 0");
        }
        puts("");
    }
    return 0;
}

发表于 2018-02-14 13:12:28 回复(0)
//我这个只能通过%50样例,不知为何

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

struct student{
    int pro[6],id;
    int sum,best,pass;
}s[10010];
bool cmp(student a,student b){
    if(a.sum!=b.sum) return a.sum>b.sum;
    else if(a.best!=b.best) return a.best>b.best;
    else return a.id<b.id;
}
int x,z,y,p[6];
void init(){                               //初始化
    for(int i=1;i<=x;i++){
        s[i].id=i;
        s[i].sum=0;
        s[i].best=0;
        s[i].pass=0;
        memset(s[i].pro,-1,sizeof(s[i].pro));  //全部科目赋值为-1(memset只能用来赋值0与-1)
    }
}
int main(){
    scanf("%d%d%d",&x,&z,&y);
    init();   //初始化
    for(int i=1;i<=z;i++) scanf("%d",&p[i]);  //输入每科满分
    for(int i=0;i<y;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);    
        if(c>=0) s[a].pass=1;    //不是-1(即编译错误)则该学生获得输出机会
        if(s[a].pro[b]<c) s[a].pro[b]=c;   //比以往提交的成绩好,覆盖
        if(c==-1&&s[a].pro[b]==-1) s[a].pro[b]=0;  //第一次提交编译错误,算为0分
    }
    for(int i=1;i<=x;i++){
            for(int j=1;j<=z;j++){
                if(s[i].pro[j]!=-1){   //在编译通过的前提下
                    if(s[i].pro[j]==p[j]) s[i].best++;  //满分次数
                    s[i].sum+=s[i].pro[j];
                }
            }
    }
    sort(s+1,s+x+1,cmp);  //排序
    int r=1;
    for(int i=1;i<=x;i++){  //从1号开始遍历
        if(s[i].pass==0) continue;  //没有一科通过,忽略这名学生
        if(i>1&&s[i].sum!=s[i-1].sum) r=i;
        printf("%d %05d %d",r,s[i].id,s[i].sum);  
        for(int j=1;j<=z;j++){
            if(s[i].pro[j]>=0) printf(" %d",s[i].pro[j]);
            else printf(" -");  //该科没有编译通过
        }
        printf("\n");
    }
    return 0;
}

发表于 2018-01-22 23:19:05 回复(0)
#include<cstdio>
#include<iostream> 
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 10010;
struct Student{
int id, sum;
int score[6]; 
int perfect;
bool flag;
}stu[maxn];
int n, k, m;
int mark[6];
bool cmp(Student a, Student b){
if(a.flag != b.flag) return a.flag > b.flag;
else if(a.sum != b.sum) return a.sum > b.sum;
else if(a.perfect != b.perfect) return a.perfect > b.perfect;
else return a.id < b.id;
}
void init(){
for(int i = 1; i <= n; i++){
stu[i].id = i;
stu[i].sum = 0;
stu[i].perfect = 0;
stu[i].flag = false;
memset(stu[i].score, -1, sizeof(stu[i].score));
}
}
int main(){ 
cin >> n >> k >> m;
init();
for(int i = 1; i <= k; i++){
cin >> mark[i];
} 
int id, pid, pscore;
for(int i = 0; i < m; i++){
cin >> id >> pid >> pscore;
if(pscore != -1)
stu[id].flag = true;
if(pscore == -1 && stu[id].score[pid] == -1)
stu[id].score[pid] = 0;
if(pscore == mark[pid] && stu[id].score[pid] < pscore)
stu[id].perfect++;
if(stu[id].score[pid] < pscore)
stu[id].score[pid] = pscore;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= k; j++){
if(stu[i].score[j] != -1)
stu[i].sum += stu[i].score[j];
}
}
sort(stu+1,stu+n+1,cmp);
int r = 1;
for(int i = 1; i <= n && stu[i].flag == true; i++){
if(i > 1 && stu[i].sum != stu[i-1].sum){
r = i;
}
printf("%d %05d %d ", r, stu[i].id, stu[i].sum);
for(int j = 1; j <= k; j++){
if(stu[i].score[j] == -1)
printf("-");
else
printf("%d",stu[i].score[j]);
if(j < k)
printf(" ");
}
printf("\n");
}
 
return 0;
}
发表于 2017-01-26 10:27:38 回复(0)
//头像 //
#include<iostream>
#include<algorithm>
using namespace std;

struct STUDENT{
 int ID;
 int *grades;
 int total;
 int complete;
 int rank;
 bool flag;
};
bool cmp( STUDENT a, STUDENT b );
int main ()
{
 int N, K, M;
 cin >> N >> K >> M;
 STUDENT *stu = new STUDENT [N+1];
 for( int i=1; i<=N; i++ )
  stu[i].grades = new int [K+1];
 int *full = new int [K+1];
 for( int i=1; i<=K; i++ )
 {
  cin >> full[i];
 }
 for( int i=1; i<=N; i++ )
 {
  for( int j=1; j<=K; j++ )
   stu[i].grades[j] = -2;
  stu[i].total = 0;
  stu[i].complete = 0;
  stu[i].ID = i;
  stu[i].flag = false;
 }
 for( int i=1; i<=M; i++ )
 {
  int num, title, grades;
  cin >> num >> title >> grades;
  if( grades > stu[num].grades[title] )
  {
   stu[num].grades[title] = grades;
   if( grade敏感词ull[title] )
    stu[num].complete++;
   if( grades >= 0 )
    stu[num].flag = true;
  }
 }
 for( int i=1; i<=N; i++ )
 {
  for( int j=1; j<=K; j++ )
  {
   if( stu[i].grades[j] > 0 )
    stu[i].total += stu[i].grades[j];
  }
 }
 sort( stu+1,stu+N+1, cmp );
 stu[1].rank = 1;
 for( int i=2; i<=N; i++ )
 {
  if( stu[i].total == stu[i-1].total )
   stu[i].rank = stu[i-1].rank;
  else
   stu[i].rank = i;
 }
 for( int i=1; i<=N; i++ )
 {
  if( stu[i].flag == false )
   continue;
  printf("%d %05d %d", stu[i].rank, stu[i].ID, stu[i].total );
  for( int j=1; j<=K; j++ )
  {
   if( stu[i].grades[j] == -2 )
    cout << " -";
   else if ( stu[i].grades[j] == -1 )
    cout << " 0";
   else if ( stu[i].grades[j] >= 0 )
    cout << " " << stu[i].grades[j];
  }
  cout << endl;
 }
 
 return 0;
}
bool cmp( STUDENT a, STUDENT b )
{
    if( a.total == b.total )
 {
  if( a.complete == b.complete )
   return a.ID < b.ID;
  else
   return a.complete > b.complete;
  }
  else
   return a.total > b.total;
} 


                                                                                    
编辑于 2015-06-13 15:09:07 回复(0)