「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