題目出處:《信息學奧賽一本通》第二章上機練習8。
題目描述
病人等級看病,編寫一個程序,將登記的病人按照以下原則排出看病的先后順序:
- 老年人(年齡 \(\ge\) 60歲)比非老年人優先看病。
- 老年人按年齡從大到小的順序看病,年齡相同的按登記的先后順序排序。
- 非老年人按登記的先后順序排序。
輸入格式
第 \(1\) 行,輸入一個不大於 \(1000\) 的正整數,表示病人的個數;
后面按照病人登記的先后順序,每行輸入一個病人的信息,包括:一個長度不大於 \(10\) 的字符串表示病人的 ID(每個病人的ID各不相同且只含數字和字母),一個整數表示病人的年齡,中間用單個空格隔開。
輸出格式
按排好的看病順序輸出病人的ID,每行一個。
樣例輸入
5
020010 40
004312 15
010133 67
023815 75
102031 23
樣例輸出
023815
010133
020010
004312
102031
題目分析
這道題目是結構體排序。
首先我們要思考的問題是怎么定義結構體:因為病人的ID包含數字和字符,所以我用一個整數 number
來表示病人的登記順序,用一個字符數組 card
來表示病人的ID,用一個整數 age
來表示病人的年齡。“病人”的英文是“patient”,所以我就開一個名為 Patient
的結構體,並在定義結構體的同時初始化結構體數組(我這里用數組 a
表示):
struct Patient {
int number; // 登記的順序
char id[11]; // 病人ID
int age; // 年齡
} a[1010];
比較函數按照題目描述來:
bool cmp(Patient a, Patient b) {
if (a.age >= 60 && b.age >= 60) { //a,b都是老年人
if (a.age != b.age) // 如果年齡不一樣
return a.age > b.age; // 按年齡從大到小排
else // 否則,年齡一樣
return a.number < b.number; // 按登記順序排
}
else if (a.age >= 60) // a是老人,b不是老人
return true; // a排前面
else if (b.age >= 60) // b是老人,a不是老人
return false; // b排前面
else // 兩個都是年輕人
return a.number < b.number; // 按登記順序排
}
需要注意的是:因為輸入格式只告訴了我們病人的ID和年齡,並沒有告訴我們登記的順序,所以我們還得主動為每一位病人標記登記的順序,最簡單的一種方式就是第 \(i\) 位病人的登記順序就是 \(i\) 。
實現代碼如下:
#include <bits/stdc++.h>
using namespace std;
struct Patient {
int number; // 登記的順序
char id[11]; // 病人ID
int age; // 年齡
} a[1010];
int n;
bool cmp(Patient a, Patient b) {
if (a.age >= 60 && b.age >= 60) { //a,b都是老年人
if (a.age != b.age) // 如果年齡不一樣
return a.age > b.age; // 按年齡從大到小排
else // 否則,年齡一樣
return a.number < b.number; // 按登記順序排
}
else if (a.age >= 60) // a是老人,b不是老人
return true; // a排前面
else if (b.age >= 60) // b是老人,a不是老人
return false; // b排前面
else // 兩個都是年輕人
return a.number < b.number; // 按登記順序排
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++) {
cin >> a[i].id >> a[i].age;
a[i].number = i; // 用 i 來表示 第 i 個病人的登記順序
}
sort(a, a+n, cmp);
for (int i = 0; i < n; i ++)
cout << a[i].id << endl;
return 0;
}