PAT-Java-Final Grading(25)

Final Grading

题目阐述

For a student taking the online course “Data Structures” on China University MOOC (http://www.icourse163.org/), to be qualified for a certificate, he/she must first obtain no less than 200 points from the online programming assignments, and then receive a final grade no less than 60 out of 100. The final grade is calculated by G = (Gmid-termx 40% + Gfinalx 60%) if Gmid-term > Gfinal, or Gfinal will be taken as the final grade G. Here Gmid-term and Gfinal are the student’s scores of the mid-term and the final exams, respectively.

The problem is that different exams have different grading sheets. Your job is to write a program to merge all the grading sheets into one.

Input Specification:

Each input file contains one test case. For each case, the first line gives three positive integers: P , the number of students having done the online programming assignments; M, the number of students on the mid-term list; and N, the number of students on the final exam list. All the numbers are no more than 10,000.

Then three blocks follow. The first block contains P online programming scores Gp’s; the second one contains M mid-term scores Gmid-term’s; and the last one contains N final exam scores Gfinal’s. Each score occupies a line with the format: StudentID Score, where StudentID is a string of no more than 20 English letters and digits, and Score is a nonnegative integer (the maximum score of the online programming is 900, and that of the mid-term and final exams is 100).

Output Specification:

For each case, print the list of students who are qualified for certificates. Each student occupies a line with the format:

StudentID Gp Gmid-term Gfinal G

If some score does not exist, output “-1” instead. The output must be sorted in descending order of their final grades (G must be rounded up to an integer). If there is a tie, output in ascending order of their StudentID’s. It is guaranteed that the StudentID’s are all distinct, and there is at least one qualified student.

Sample Input:
6 6 7
01234 880
a1903 199
ydjh2 200
wehu8 300
dx86w 220
missing 400
ydhfu77 99
wehu8 55
ydjh2 98
dx86w 88
a1903 86
01234 39
ydhfu77 88
a1903 66
01234 58
wehu8 84
ydjh2 82
missing 99
dx86w 81
Sample Output:
missing 400 -1 99 99
ydjh2 200 98 82 88
dx86w 220 88 81 84
wehu8 300 55 84 84


题目分析

这是去年冬天的第二道题,做完感觉PAT号称国内的托福考试此言非虚,题目要求最后通过考试的所有人信息,很明显学生考试信息包括姓名name,平时作业成绩work,期中测试成绩mid,期末测试成绩fin,然后是最后总成绩score,那么就用一个类Student来表示一个学生的所有信息就行,首先平时成绩没有或者低于200的就肯定通不过,所以不用记录,使用Hash<String, Student>来将姓名和某个具体学生进行映射;然后输入P个平时成绩时,低于200的忽略,否则放入map中,然后输入M个期中测试时,如果学生不在map中则忽略,否则定位找到该学生,更新其mid成绩,注意这里mid,fin,和score都初始化为-1,接下来的N个期末成绩里,求算最终总成绩时加上判断仔细点,不要遗漏细节,算出最终的score即可;如果有人此时的总成绩小于60,那么就将它的成绩还原为初始值-1;最后将所有人成绩排序,并输出所有总成绩里不为-1的学生信息;

题目并不需要什么特别精妙的解法让你眼前一亮但是在写完代码提交后总是最后一个点万年超时,我想尽一切办法优化所有我能想到的地方,但是还是承认到果然PAT不是面向Java的一门算法考试,同样的一段代码翻译成C就轻松通过,因为Java代码运行起来的确是比c要慢很多,看了下后来用c通过的提交结果,前面20分都只花了2ms,但是最后一个点却花了62ms,可想而知,此刻你的输入得多大!而Java的运行慢,首先就在于输入Scanner,你一个next()或者nextInt(),我想肯定是比c慢了不少的,我试过一行一行的读入,然后再进行转换,但是但优化的效益并不明显。不过经过这一点,也的确是看透了想过PAT,还是得用C!不过在给java代码做优化的过程中也学会了不少技巧,这篇帖子应该是PAT系列里最后一篇还用Java写的了把。


代码实现
  • JavaCode
package PAT;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] temp = sc.nextLine().split(" ");
        int N = Integer.parseInt(temp[0].trim());
        int M = Integer.parseInt(temp[1].trim());
        int F = Integer.parseInt(temp[2].trim());

        Map<String, Student> map = new HashMap<>();
        int val;
        String str;

        for (int i=0; i<N; i++) {
            str = sc.next();
            val = sc.nextInt();
            if(val < 200) continue;
            Student st = new Student(str, val);
            map.put(str, st);
        }

        for (int i=0; i<M; i++) {
            str = sc.next();
            val = sc.nextInt();
            if (map.containsKey(str))
                map.get(str).mid =val;
        }

        for (int i=0; i<F; i++) {
            str = sc.next();
            val = sc.nextInt();
            if (!map.containsKey(str)) continue;
            Student st = map.get(str);
            st.fin = val;
            if (st.mid <= val) st.score = val;
            else {
                double v = 0.4 * st.mid + 0.6 * val + 0.5; //避开Math.round函数的好方法
                st.score = (int)v;
            }
            if (val < 60) {
                st.score = -1; //很重要,方便后面排序的优化
            }
        }
        sc.close(); //养成关闭流的好习惯

        List<Student> list = new ArrayList<>(map.values());
        Collections.sort(list); //调用java自己的排序方法,默认从小到大,自己改写compareTo方法让从大到小输出
        for (Student st : list) {
            if (st.score == -1) break; //避免无畏的循环
            System.out.println(st.name + " " + st.work + " " + st.mid + " " +  st.fin + " " + st.score); 
        }
    }

}

class Student implements Comparable<Student> {
    String name;
    int work, mid, fin, score;
    public Student(String name, int score) {
        this.name = name;
        this.work = score;
        mid = -1;
        fin = -1;
        score = -1;
    }
    @Override
    public int compareTo(Student o) {
//      return res == o.res ? name.compareTo(o.name) : o.res - res; //这一段代码其实也足以
        if (score != o.score) return o.score - score;
        if (score == -1) return -1;
        return name.compareTo(o.name);
    }


}
  • C-Code
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
struct node {
    string name;
    int gp, gm, gf, g;
};

bool cmp(node a, node b) {
    return a.g != b.g ? a.g > b.g : a.name < b.name;
}
map<string, int> idx;
int main() {
    int p, m, n, score, cnt = 1;
    cin >> p >> m >> n;
    vector<node> v, ans;
    string s;
    for (int i = 0; i < p; i++) {
        cin >> s >> score;
        if (score >= 200) {
            v.push_back(node{ s, score, -1, -1, 0 });
            idx[s] = cnt++;
        }
    }
    for (int i = 0; i < m; i++) {
        cin >> s >> score;
        if (idx[s] != 0) v[idx[s] - 1].gm = score;
    }
    for (int i = 0; i < n; i++) {
        cin >> s >> score;
        if (idx[s] != 0) {
            int temp = idx[s] - 1;
            v[temp].gf = v[temp].g = score;
            if (v[temp].gm > v[temp].gf) v[temp].g = int(v[temp].gm * 0.4 + v[temp].gf * 0.6 + 0.5);
        }
    }

    for (int i = 0; i < v.size(); i++)
        if (v[i].g >= 60) ans.push_back(v[i]);
    sort(ans.begin(), ans.end(), cmp);
    for (int i = 0; i < ans.size(); i++)
        printf("%s %d %d %d %d\n", ans[i].name.c_str(), ans[i].gp, ans[i].gm, ans[i].gf, ans[i].g);
    return 0;
}
思考总结
  • 有用List存放Student,反反复复的的v地方然后Map<String,Integer> 形式中int存放student的索引,我认为这一种和笔者代码实现的直接用map存student差别并不大,差别其实只是在于map最后得取出values集合,而这个可以直接在list里排序罢了。
  • C代码里map中如果不存在该键,默认值int为0;
  • 上述 Java代码,提交后最后一个6分点超时,所以25分里只能得到19分,为什么要用c?你一个可以拿满分的题,就因为想偷懒,用最熟悉的语言而少拿6分,得不偿失。所以还是大一当时学的c代码,还是捡起来好好看看,争取拿个及格分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值