PAT-甲級-1080-Graduate Admission(30)

這篇博文的JAVA代碼有一個測試點未通過
在這裏插入圖片描述

題目描述

It is said that in 2011, there are about 100 graduate schools ready to proceed over 40,000 applications in Zhejiang Province. It would help a lot if you could write a program to automate the admission procedure.

Each applicant will have to provide two grades: the national entrance exam grade GE, and the interview grade GI. The final grade of an applicant is (GE+GI)/2. The admission rules are:

  • The applicants are ranked according to their final grades, and will be admitted one by one from the top of the rank list.
  • If there is a tied final grade, the applicants will be ranked according to their national entrance exam grade GE. If still tied, their ranks must be the same.
  • Each applicant may have K choices and the admission will be done according to his/her choices: if according to the rank list, it is one’s turn to be admitted; and if the quota of one’s most preferred shcool is not exceeded, then one will be admitted to this school, or one’s other choices will be considered one by one in order. If one gets rejected by all of preferred schools, then this unfortunate applicant will be rejected.
  • If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.

輸入格式:

Each input file contains one test case.

Each case starts with a line containing three positive integers: N (≤40,000), the total number of applicants; M (≤100), the total number of graduate schools; and K (≤5), the number of choices an applicant may have.

In the next line, separated by a space, there are M positive integers. The i-th integer is the quota of the i-th graduate school respectively.

Then N lines follow, each contains 2+K integers separated by a space. The first 2 integers are the applicant’s GE and GI, respectively. The next K integers represent the preferred schools. For the sake of simplicity, we assume that the schools are numbered from 0 to M−1, and the applicants are numbered from 0 to N−1.

輸出格式:

For each test case you should output the admission results for all the
graduate schools. The results of each school must occupy a line, which
contains the applicants’ numbers that school admits. The numbers must be
in increasing order and be separated by a space. There must be no extra
space at the end of each line. If no applicant is admitted by a school,
you must output an empty line correspondingly.

輸入樣例:

11 6 3
2 1 2 2 2 3
100 100 0 1 2
60 60 2 3 5
100 90 0 3 4
90 100 1 2 0
90 90 5 1 3
80 90 1 0 2
80 80 0 1 2
80 80 0 1 2
80 70 1 3 2
70 80 1 2 3
100 100 0 2 4

輸出樣例:

0 10
3
5 6 7
2 8
			//這就是有個空格輸出
1 4

題目信息:

作者: CHEN, Yue

單位: 浙江大學

時間限制: 250 ms

內存限制: 64 MB

代碼長度限制: 16 KB

題目大意

這道題大意是講的學生報考選擇學校的過程,寫一個程序處理學生的報考信息

第一行輸入三個數,依次分別爲N:有N位考生報考,M:一共可以報的學校有M個,K:每個考生可以填報K個志願學校

第二行輸入M個數,第i個數代表第i所學校準備錄取的人數,即招生額度

接下來N行,每行輸入的是一個學生的報考信息有K+2個數,前兩個數是GE:初試成績,GI:面試成績,接下來的K個數代表所填報的志願學校

我們要做的是模擬學校錄取的過程:

  1. 先按照考生的總分(GE+GI)/2從高到低排序,總分相同的按照GE從高到低排序,如果GE也相同,那麼兩個學生的排名就相同
  2. 學生從排名最高的開始錄取,對於每個考生按照K個志願的先後順序考慮
    • 如果當前志願學校已經招收的人數未達到招生額度,則錄取這名學生
    • 如果當前志願學校已經招滿,但是這名學生與該校上一個錄取的學生排名相同,那麼該學校不管是否收滿,都要錄取這名學生
    • 如果上面的情況都不滿足,當前志願學校就不能錄取這名學生,學生就要轉而考慮下一個志願學校
    • 如果所有志願學校都無法錄取,則這名考生徹底落榜
  3. 最後按照學校的順序,將每一個學校錄取的學生按照原序號遞增順序輸出

分析

  • 考生按照總成績/2進行排序,其實和總成績排序是相同的,所以我們直接按照總成績排序
  • 一名學生只能被唯一學校錄取
  • 當前志願學校已經招滿時,當前學生與該校上一個錄取的學生排名相同則錄取,因爲我們是按照分數最高到分數最低學生的順序錄取的,所以我們直接比較當前學校最後一名學生的排名與當前學生的排名

注意:

  • 輸出的時候輸出的是學生的原序號,就是沒有排序之前的順序
  • 輸出每個學校學生的序號時,要按照遞增的順序,要把每個學校的學生排一遍,否則最後一個樣例出現的就是4 1而不是1 4
  • 沒有學校也要輸出空行

重點代碼步驟

  1. 對於每個學生
  • 按順序考慮該學生的每個志願
    • 如果當前志願沒有錄滿學生,錄取該學生
    • 如果當前志願錄滿了
      • 如果當前學生與該志願最後錄取的學生排名相同,則也錄取當前學生學生
  1. 將每個學校錄取的學生按照學生序號從小到大排序,否則最後一個樣例就是 4 1而不是1 4
  2. 輸出每個學校的學生

代碼實現-JAVA

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main{
	public static void main(String[] args) throws IOException{
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		String[] tempStrArr = bf.readLine().split(" ");
		// N考生
		int N = Integer.parseInt(tempStrArr[0]);
		// M學院
		int M = Integer.parseInt(tempStrArr[1]);
		// K個志願
		int K = Integer.parseInt(tempStrArr[2]);

		// 每個的學校錄取限額
		int[] schoolCon = new int[M];
		tempStrArr = bf.readLine().split(" ");
		for(int i=0; i<M; i++)
			schoolCon[i] = Integer.parseInt(tempStrArr[i]);
		
		// 所有學生
		Student[] allStu = new Student[N];
		for(int i=0; i<N; i++) {
			tempStrArr = bf.readLine().split(" ");
			// 創建學生時給學生序號
			Student newStu = new Student(i,tempStrArr);
			allStu[i] = newStu;
		}
		
		// 按照總分非遞增排序,總分相同按照GE排序
		Arrays.sort(allStu);
		// 第一位的同學排名爲1
		allStu[0].rank = 1;
		for(int i=1; i<N; i++) {
			// 如果當前的同學與上一位同學的總分和GE都相同則排名相同
			// 相同排名按照 1 2 3 3 5,不連續的這種方式處理
			if((allStu[i].grade == allStu[i-1].grade) && (allStu[i-1].GE == allStu[i].GE)) {
				allStu[i].rank = allStu[i-1].rank;
			}else allStu[i].rank = i+1;
		}

		// 每個學校,學校裏放錄取的學生
		List<Student>[] school = new List[M];
		for(int i=0; i<M; i++) {
			school[i] = new ArrayList<Student>();
		}
		
		// 對於每個學生
		for(int i=0; i<N; i++) {
		// 按順序考慮該學生的每個志願
			for(int j=0; j<K; j++) {
				// 當前學生的當前志願
				int nowToSchool = allStu[i].toSchool[j];
				// 如果當前志願沒有錄滿學生
				if(school[nowToSchool].size() < schoolCon[nowToSchool]) {
					// 錄取該學生
					school[nowToSchool].add(allStu[i]);
					// 每個學生只能錄取一個學校,所以考慮下一個學生
					break;
				}
				else {// 如果當前志願錄滿了
				// 如果當前學生與該志願最後錄取的學生排名相同,則也錄取當前學生學生
					if(school[nowToSchool].get(school[nowToSchool].size()-1).rank == allStu[i].rank) {
					// 錄取該學生
					school[nowToSchool].add(allStu[i]);
					// 每個學生只能錄取一個學校,所以考慮下一個學生
					break;
					}
				}
			}
		}
		
		// 將每個學校錄取的學生按照學生序號從小到大排序,否則最後一個樣例就是 `4 1`而不是`1 4`
		for(int i=0; i<M; i++) {
			Collections.sort(school[i],new Comparator<Student>() {
				public int compare(Student o1, Student o2) {
					return o1.ID - o2.ID;
				}
				
			});
		}
		
		// 輸出每個學校的學生
		for(int i=0; i<M; i++) {
			for(int j=0; j<school[i].size(); j++) {
				if(j>0)
					System.out.print(" ");
				System.out.print(school[i].get(j).ID);
			}
			System.out.println();
		}
		
	}
}

class Student implements Comparable<Student>{
	int ID;
	int grade;
	// 志願學校
	int[] toSchool;
	int GE;
	// 排名
	int rank;
	
	// 將讀取到的一整行都輸入進行處理
	public Student(int ID, String[] bfRead) {
		this.ID = ID;
		this.GE = Integer.parseInt(bfRead[0]);
		this.grade = GE + Integer.parseInt(bfRead[1]);
		// 給志願學校賦值
		toSchool = new int[bfRead.length -2];
		for(int i=2; i<bfRead.length; i++) {
			toSchool[i-2] = Integer.parseInt(bfRead[i]);
		}
	}
	
	@Override
	public int compareTo(Student o) {
		// 按總成績排序
		int s =  o.grade - this.grade;
		if(s == 0) // 總成績相同按GE排序
			return  o.GE - this.GE;
		else return s;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章