「CSP-J2019」公交換乘 題解 (模擬)


題目摘要


題目描述

著名旅游城市 B 市為了鼓勵大家采用公共交通方式出行,推出了一種地鐵換乘公交車的優惠方案:

  1. 在搭乘一次地鐵后可以獲得一張優惠票,有效期為 45 分鍾,在有效期內可以消耗這張優惠票,免費搭乘一次票價不超過地鐵票價的公交車。在有效期內指開始乘公交車的時間與開始乘地鐵的時間之差小於等於 45 分鍾,即:\(t_{bus} - t_{subway} \leq 45\)
  2. 搭乘地鐵獲得的優惠票可以累積,即可以連續搭乘若干次地鐵后再連續使用優惠票搭乘公交車。
  3. 搭乘公交車時,如果可以使用優惠票一定會使用優惠票;如果有多張優惠票滿足條件,則優先消耗獲得最早的優惠票。

現在你得到了小軒最近的公共交通出行記錄,你能幫他算算他的花費嗎?

傳送門

分析


存儲方式

每一行將會有 3 個整數,姑且將它們記為 \(a,b,c\)

我們可以開三個數組記錄它們:

const int maxn=100005;
int a[maxn], b[maxn], c[maxn]; 

但是我更喜歡使用 struct,將幾個數組綁在一起,不怕意外的丟失:

const int maxn = 100005;
struct C {
    int a, b, c;
} d[maxn];

不免覺得每次都敲d[i].name太麻煩,於是我使用了一個小技巧:

#define da(i) d[i].a
#define db(i) d[i].b
#define dc(i) d[i].c

另外,需要一個數組記錄趕地鐵獲得的優惠券,初學者可以定義ticket[maxn],但是這次我使用的是\(STL\)中的vector

vector<int> ticket;

\(ticket\) 記錄的是趕地鐵時的 \(i\) ,但是在 \(ticket\) 中並不是全部都可以用掉,所以我們還需要一個 \(start\) 去作為起始點遍歷 \(ticket\) :

#include <bits/stdc++.h>
#define da(i) d[i].a
#define db(i) d[i].b
#define dc(i) d[i].c
using namespace std;
const int maxn = 100005;
int n, ans;
struct C {
    int a, b, c;
} d[maxn];
vector<int> ticket;
int start;

算法分析(模擬)

1.如果趕的是 subway 那么只需要將其存入 \(ticket\) 中 ,如果趕的是 bus ,那么繼續執行:

if (!da(i)) {
    ticket.push_back(i);
    t.size()++;
    continue;
}

2.將那些過期的車票過濾掉

因為題目中寫了保證出行記錄是按照開始乘車的時間順序給出的,且不會有兩次乘車記錄出現在同一分鍾,所以我們可以放心地按時間順序篩選:

while (start < t.size()) {
    if (dc(i) - dc(ticket[start]) <= 45)
    break;
    start++;
}

3.遍歷

for (int j = start; j < t.size(); j++)

其中,公交票價不能超過優惠券的價格:

if (db(ticket[j]) < db(i))
    continue;

另外,使用過的券也不能用了:

if (da(ticket[j]))
    continue;

同時將使用的券標為

da(ticket[j]) = 1;

4.當然,還要計算 \(ans\),這個可以在輸入的時候就加上 \(db(i)\) ,如果乘地鐵就啥都不管,如果不能使用優惠券也不管,如果用了,就在循環里加一句:

ans -= db(i);
break;

完整代碼展示


將上文串聯起來:

#include <bits/stdc++.h>
#define da(i) d[i].a
#define db(i) d[i].b
#define dc(i) d[i].c
using namespace std;
const int maxn = 100005;
int n, ans;
struct C {
    int a, b, c;
} d[maxn];
vector<int> ticket;
int start;
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &da(i), &db(i), &dc(i));
        ans += db(i);
        if (!da(i)) {
            ticket.push_back(i);
            t.size()++;
            continue;
        }
        while (start < t.size()) {
            if (dc(i) - dc(ticket[start]) <= 45)
                break;
            start++;
        }
        for (int j = start; j < t.size(); j++) {
            if (da(ticket[j]))
                continue;
            if (db(ticket[j]) < db(i))
                continue;
            da(ticket[j]) = 1;
            ans -= db(i);
            break;
        }
    }
    printf("%d", ans);
    return 0;
}

-- END --


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM