小韦先生@NOIP普及グループ-2007-奨学金


小韦先生@NOIP普及グループ-2007-奨学金
タイトル:
説明
ある小学校は最近、一部を出して成績優秀な上位5人に奨学金を支給しようとした.期末、すべての学生はすべて3つの授業の成績があります:国語、数学、英語.まず総点の高さから低さまで並べ替えて、もし2人の学生の総点が同じならば、更に国語の成績の高さから低さまで並べ替えて、もし2人の学生の総点と国語の成績がすべて同じならば、学号の小さい学生が前に並ぶことを規定して、このようにして、すべての学生の並べ替えは唯一確定します.
タスク:入力した3科目の成績から総点を計算し、上記のルールでソートし、上位5名の学生をランキング順に出力します.
の学号と総点.上位5人の学生のうち、奨学金は人によって異なるので、上記のルールに厳格に従ってソートしなければなりません.
たとえば、ある正解で、最初の2行の出力データ(行ごとに2つの数:学番、総得点)が次のように出力されている場合:
7 279
5 279
この2行のデータの意味は、総得点が最も高い2人の学生の学号が7日、5日の順だ.この2人の学生の総得点は279(総得点は入力した国語、数学、英語の3科の成績の和に等しい)だが、学号7の学生の国語の成績はもっと高い.上位2位の出力データが次の場合:
5 279
7 279
出力エラー処理で得点できません.
入力
入力にはn+1行が含まれます.
第1の行為は正の整数nで、同校が選考に参加した学生の人数を表す.
2行目からn+1行目、各行に3つのスペースで区切られた数字があり、各数字は0から100の間にある.j行目の3つの数字は、j-1という学生の国語、数学、英語の成績を順に表す.生徒毎の学番は入力順に1~n(入力データの行番マイナス1)とする.与えられたデータはすべて正しいので、検査する必要はありません.
しゅつりょく
出力は5行で、各行はスペースで区切られた2つの正の整数で、上位5人の学生の学号と総点を順番に表します.
入力サンプル1
6 
90 67 80 
87 66 91 
78 89 91 
88 99 77 
67 89 64 
78 89 98

出力サンプル1
6 265 
4 264 
3 258 
2 244 
1 237

入力サンプル2
8 
80 89 89 
88 98 78 
90 67 80 
87 66 91 
78 89 91 
88 99 77 
67 89 64 
78 89 98

出力サンプル2
8 265 
2 264 
6 264 
1 258 
5 258

ヒント
50%のデータが満たされている:各学生の総成績はそれぞれ異なる.
100%のデータ満足:6<=n<=300
問題:
考え方:
全体的な考え方:
これは構造体の配列の並べ替えのテーマで、並べ替えの規則は:1.総点が等しくない場合は、総点の高さから低さまで2.総点が等しい場合、国語の成績によって高いから低いまで並ぶ.総得点が等しく、国語の成績も等しい場合は、学号に従って小さいから大きいまで並べます.
具体的な手順:
1.構造体および構造体配列を定義します.
	const int N = 310;
	struct student {
		int id;   //    
		int ch;   //     ,ch   Chinese       
		int ma;   //     ,ma   math        
		int en;   //     ,en   English        
		int sum;  //    
	} stu[N];

2.nを定義し、nを入力します.3.各学生の学号を取得し、n人の学生の国語の成績、数学の成績と英語の成績を入力し、各学生の総得点を算出する.
	for (int i = 1; i <= n; i++) {  //   n     
		stu[i].id = i;  //       i     i           
		//     i         ,    ,    
		cin >> stu[i].ch >> stu[i].ma >> stu[i].en;  
		stu[i].sum = stu[i].ch + stu[i].ma + stu[i].en;  //     i         
	}

4.sortで構造体配列stuをソートする:
	//   sort        stu   ,            stu + 1   stu + n + 1
	//    stu          1~n,         stu + 1
	//                      ,    stu + n + 1
	// cmp               ,       
	sort(stu + 1, stu + n + 1, cmp);

5.配列された構造体配列stuの最初の5要素の学号と総点を出力する.
	for (int i = 1; i <= 5; i++) {  //     5           
		cout << stu[i].id << " " << stu[i].sum << endl;
	}

6.cmp関数の実装:
	// sort      ,         
	//      bool  ,    sort          
	//       student      ,      student               
	bool cmp(student a, student b) {
		if (a.sum != b.sum ) {  //           
			return a.sum > b.sum;//     a.sum > b.sum,               
		} else if (a.ch != b.ch) {  //         ,        
			return a.ch > b.ch; //     a.ch > b.ch,                 
		} else {  //         ,        
			return a.id < b.id;  //     a.id < b.id,                
		}
	}

完全なコード:
#include 

using namespace std;

const int N = 310;
struct student {
	int id;   //    
	int ch;   //     ,ch   Chinese       
	int ma;   //     ,ma   math        
	int en;   //     ,en   English        
	int sum;  //    
} stu[N];

// sort      ,         
//      bool  ,    sort          
//       student      ,      student               
bool cmp(student a, student b) {
	if (a.sum != b.sum ) {  //           
		return a.sum > b.sum;  //     a.sum > b.sum,               
	} else if (a.ch != b.ch) {  //         ,        
		return a.ch > b.ch;  //     a.ch > b.ch,                 
	} else {  //         ,        
		return a.id < b.id;  //     a.id < b.id,                
	}
}

int main() {

	int n;  
	cin >> n;
	for (int i = 1; i <= n; i++) {  //   n     
		stu[i].id = i;  //       i     i           
		cin >> stu[i].ch >> stu[i].ma >> stu[i].en;  //     i         ,    ,     
		stu[i].sum = stu[i].ch + stu[i].ma + stu[i].en;  //     i         
	}
	//   sort        stu   ,            stu + 1   stu + n + 1
	//    stu          1~n,         stu + 1
	//                      ,    stu + n + 1
	// cmp               ,       
	sort(stu + 1, stu + n + 1, cmp);
	for (int i = 1; i <= 5; i++) {  //     5           
		cout << stu[i].id << " " << stu[i].sum << endl;
	}

	return 0;
}