2020年團隊程式設計天梯賽L2 -2 口罩發放

一支萬寶路發表於2020-11-29

L2 - 2 口罩發放(25分)

為了抗擊來勢洶洶的 COVID19 新型冠狀病毒,全國各地均啟動了各項措施控制疫情發展,其中一個重要的環節是口罩的發放。

某市出於給市民發放口罩的需要,推出了一款小程式讓市民填寫資訊,方便工作的開展。小程式收集了各種資訊,包括市民的姓名、身份證、身體情況、提交時間等,但因為資料量太大,需要根據一定規則進行篩選和處理,請你編寫程式,按照給定規則輸出口罩的寄送名單。

輸入格式:

輸入第一行是兩個正整數 D D D P P P 1 ≤ D , P ≤ 30 1≤D,P≤30 1D,P30),表示有 D D D 天的資料,市民兩次獲得口罩的時間至少需要間隔 P P P 天。

接下來 D 塊資料,每塊給出一天的申請資訊。第 i 塊資料( i = 1 , ⋯ , D i=1,⋯,D i=1,,D)的第一行是兩個整數 T i Ti Ti S i Si Si 1 ≤ T i , S ​ i ≤ 1000 1≤Ti,S​i ≤1000 1Ti,Si1000),表示在第 i i i 天有 T ​ i T​i Ti 條申請,總共有 S ​ i S​i Si個口罩發放名額。隨後 T ​ i T​i Ti 行,每行給出一條申請資訊,格式如下:

姓名
身份證
身體情況
提交時間

給定資料約束如下:
姓名是一個長度不超過 10 的不包含空格的非空字串;
身份證號是一個長度不超過 20 的非空字串;
身體情況是 0 或者 1,0 表示自覺良好,1 表示有相關症狀;
提交時間 h h : m m hh:mm hh:mm,為24小時時間(由 00 : 00 00:00 00:00 23 : 59 23:59 23:59。例如 09 : 08 09:08 09:08。)。
注意,給定的記錄的提交時間不一定有序
身份證號 各不相同,同一個身份證號被認為是同一個人,資料保證同一個身份證號姓名是相同的。

能發放口罩的記錄要求如下:
身份證號 必須是 18 位的數字(可以包含前導0);
同一個身份證號若在第 i i i 天申請成功,則接下來的 P P P 天不能再次申請。也就是說,若第 i i i 天申請成功,則等到第 i + P + 1 i+P+1 i+P+1 天才能再次申請;
在上面兩條都符合的情況下,按照提交時間的先後順序發放,直至全部記錄處理完畢或 S ​ i S​i Si 個名額用完。如果提交時間相同,則按照在列表中出現的先後順序決定。

輸出格式:

對於每一天的申請記錄,每行輸出一位得到口罩的人的姓名及身份證號,用一個空格隔開。順序按照發放順序確定。

在輸出完發放記錄後,你還需要輸出有合法記錄的、身體狀況為 1 的申請人的姓名及身份證號,用空格隔開。順序按照申請記錄中出現的順序確定,同一個人只需要輸出一次。

輸入樣例

4 2
5 3
A 123456789012345670 1 13:58
B 123456789012345671 0 13:58
C 12345678901234567 0 13:22
D 123456789012345672 0 03:24
C 123456789012345673 0 13:59
4 3
A 123456789012345670 1 13:58
E 123456789012345674 0 13:59
C 123456789012345673 0 13:59
F F 0 14:00
1 3
E 123456789012345674 1 13:58
1 1
A 123456789012345670 0 14:11

輸出樣例

D 123456789012345672
A 123456789012345670
B 123456789012345671
E 123456789012345674
C 123456789012345673
A 123456789012345670
A 123456789012345670
E 123456789012345674

樣例解釋

  • 第一行到第三行為第一天的合法申請
  • 第四行到第五行為第二天的合法申請
  • 第三天沒有合法申請
  • 第六行為第四天的合法申請
  • 第七行和第八行輸出這四天裡身體情況為 1 1 1的合法申請

程式碼

這是我賽後補題,因此只對樣例測試過,不知道是否正確(逃)

#include<bits/stdc++.h>

#define int long long
#define IOS ios::sync_with_stdio(false)
using namespace std;
struct Person {
    string name;    // 姓名
    string ID;      // 身份證
    int situation;  // 病況 0 或 1
    string post;    // 申請時間
    int date;       // 在第幾天申請的
    int order;      // 申請順序
};

vector<Person> v, v1;       // v負責記錄合法的申請,v1負責記錄身體情況為1的合法申請
map<string, Person> m, m1;  // m負責判斷該身份證號之前是否進行過合法申請(即是否被收進了v中),m1負責判斷該合法申請是否情況為1(即是否被收進了v1中)
int d, p;                   // 題目輸入的天數,間隔數

bool check_time(string s1, string s2, int d1, int d2) {     // 將時間轉化為分鐘數,再判斷是否間隔足夠的天數
    int h1 = (s1[0] - '0') * 10 + (s1[1] - '0');
    int h2 = (s2[0] - '0') * 10 + (s2[1] - '0');
    int m1 = (s1[3] - '0') * 10 + (s1[4] - '0');
    int m2 = (s2[3] - '0') * 10 + (s2[4] - '0');
    int time1 = d1 * 3600 + h1 * 60 + m1;
    int time2 = d2 * 3600 + h2 * 60 + m2;
    int sub = p * 3600;
    if (time2 - time1 >= sub)
        return true;
    else
        return false;
}

bool check_id(Person person) {      // 判斷身份證號是否合法
    string id = person.ID;
    if (id.size() != 18)
        return false;
    for (int i = 0; i < id.size(); i++) {
        if (id[i] < '0' || id[i] > '9')
            return false;
    }
}

bool cmp(Person a, Person b) {     // 用於 v 的比較,需要比較申請時間和申請順序
    string s1 = a.post;
    string s2 = b.post;
    int d1 = a.date;
    int d2 = b.date;
    int h1 = (s1[0] - '0') * 10 + (s1[1] - '0');
    int h2 = (s2[0] - '0') * 10 + (s2[1] - '0');
    int m1 = (s1[3] - '0') * 10 + (s1[4] - '0');
    int m2 = (s2[3] - '0') * 10 + (s2[4] - '0');
    int time1 = d1 * 3600 + h1 * 60 + m1;
    int time2 = d2 * 3600 + h2 * 60 + m2;
    if (time1 == time2)
        return a.order < b.order;
    else
        return time1 < time2;
}

bool cmp2(Person a, Person b) {     // 用於 v1 的比較,比較申請順序即可
    return a.order < b.order;
}


signed main() {
    IOS;
    cin >> d >> p;
    Person person;
    int cnt = 0;
    for (int i = 1; i <= d; i++) {
        int t, s;
        cin >> t >> s;
        v.clear();
        for (int j = 1; j <= t; j++) {
            cnt++;                              // 每有一條申請,cnt就加一,記錄申請順序
            cin >> person.name >> person.ID
                >> person.situation >> person.post;
            person.date = i;                    // 天數
            person.order = cnt;                 // 申請順序
            string id = person.ID;
            if (check_id(person) && s) {        // 如果身份證合法 且 還有當天還有發放名額
                if (m.count(id)) {              // 如果之前進行過合法申請
                    if (check_time(id, person.ID, m[id].date, person.date)) {   // 檢查是否間隔足夠的天數
                        m[id] = person;         // 更新申請時間
                        v.push_back(person);    // 記錄
                        s--;                    // 發放名額減一
                    }
                } else {                        // 之前沒有進行過合法申請
                    m[person.ID] = person;
                    v.push_back(person);        // 記錄
                    s--;
                }
            }
            if (person.situation == 1 && m.count(person.ID) && !m1.count(person.ID)) {  // 如果合法申請過,且身體情況為1,收入v1中
                m1[person.ID] = person;
                v1.push_back(person);
            }
        }
        sort(v.begin(), v.end(), cmp);
        for (int j = 0; j < v.size(); j++) {
            cout << v[j].name << " " << v[j].ID << endl;
        }
    }

    sort(v1.begin(), v1.end(), cmp2);
    for (int j = 0; j < v1.size(); j++) {
        cout << v1[j].name << " " << v1[j].ID << endl;
    }
    return 0;
}

參考:點這裡

相關文章