1 条题解
-
0
题意分析
本题描述了一个高速公路收费的场景。罗马的高速公路采用自动收费模式,其中特定的 CDVII 公路收费规则如下:每公里收费金额依据当天开始行驶的时间而定,每个入口和出口的摄像头会记录车辆的车牌号。每月会给车辆注册车主发送账单,费用包含按行驶公里数(依行驶起始时间对应的费率)计算的金额、每次行程 1 美元以及 2 美元的账户管理费。输入分为两部分,一是一行 24 个非负整数,代表一天中每个小时的收费标准(美分/公里);二是若干条车辆进出记录,每条记录包含车牌号(最多 20 个字母数字字符)、时间日期(mm:dd:hh:mm)、“enter”或“exit”标识以及进出位置(距离公路一端的公里数),所有日期在同一个月内。“enter”记录需与按时间顺序的下一个“exit”记录配对,未配对的记录将被忽略。输出要求按照车牌号的字母顺序,为每辆车输出车牌号和总费用。
解题思路
- 数据读取与存储:首先读取 24 个整数,存储到数组
cost
中,作为不同时段的收费标准。接着,使用结构体Photo
来存储每条车辆进出记录,包括车牌号、日期中的日、小时、分钟、进出标识(用 0 表示进入,1 表示离开)和位置信息。通过循环将所有记录存储到数组p
中。 - 数据排序:定义比较函数
cmp
,先按车牌号的字典序排序,若车牌号相同,则按日期的日、小时、分钟排序,若仍相同则按进出标识排序。使用sort
函数对数组p
进行排序,以便后续匹配进出记录。 - 费用计算:遍历排序后的数组
p
,当遇到“enter”记录时,暂存该记录;当遇到“exit”记录且之前有暂存的“enter”记录,并且两者车牌号相同时,计算此次行程的费用。费用计算方式为:行程距离(离开位置与进入位置差值的绝对值)乘以进入时刻对应的每公里收费标准,再加上每次行程固定的 1 美元(100 美分)。将计算结果累加到map
容器m
中,m
的键为车牌号,值为总费用。 - 结果输出:遍历
map
容器m
,对于每个车辆,将其总费用加上每月固定的 2 美元(200 美分)账户管理费,然后以“车牌号 $总费用”的格式输出,总费用保留两位小数。
示例代码
/* POJ2648 ZOJ1849 CDVII */ #include <iostream> #include <sstream> #include <algorithm> #include <map> #include <cstdio> #include <cstring> using namespace std; const int N = 24; int cost[N]; const int M = 1000; const int L = 20; struct Photo { char license[L + 1]; int d, h, m, io, dis; } p[M]; bool cmp(const Photo& a, const Photo& b) { int eq = strcmp(a.license, b.license); if(eq != 0) return eq < 0; if(a.d != b.d) return a.d < b.d; if(a.h != b.h) return a.h < b.h; if(a.m != b.m) return a.m < b.m; return a.io < b.io; } int main() { string line; for(int flag = 0;; flag = 1) { getline(cin, line); if(line == "") break; if(flag) printf("\n"); map<string, int> m; stringstream sin(line); for(int i = 0; i < N; i++) sin >> cost[i]; int n = 0; while(getline(cin, line) && line != "") { char t[8]; sscanf(line.c_str(), "%s %*d:%d:%d:%d %s %d", p[n].license, &p[n].d, &p[n].h, &p[n].m, t, &p[n].dis); p[n].io = t[1] == 'n' ? 0 : 1; n++; } sort(p, p + n, cmp); Photo pt; for(int i = 0; i < n; i++) { if(p[i].io == 0) pt = p[i]; else { if(pt.io != -1) { if(strcmp(pt.license, p[i].license) == 0) m[string(pt.license)] += abs(p[i].dis - pt.dis) * cost[pt.h] + 100; pt.io = -1; } } } for(map<string, int>::iterator iter = m.begin(); iter != m.end(); iter++) printf("%s $%.2f\n", iter->first.c_str(), (iter->second + 200) / 100.0); } return 0; }
注意事项
- 数据类型与范围:虽然本题输入数据规模未明确提示会导致整数溢出,但要注意存储费用和距离等数据时,使用合适的数据类型,避免因数据范围问题产生错误。
- 输入解析:使用
stringstream
和sscanf
解析输入时,要确保输入格式符合要求。特别是sscanf
中的格式字符串,要准确匹配输入的格式,否则可能导致解析错误。 - 排序规则:
cmp
函数中的排序规则要严格按照车牌号、日期、进出标识的优先级进行,确保排序结果正确,以便后续准确匹配进出记录。 - 费用计算与单位转换:费用计算时要注意单位统一,输入的收费标准是美分/公里,而输出的总费用是美元,需要进行正确的单位转换。同时,每次行程的 1 美元和每月的 2 美元管理费不要遗漏。
- 边界情况处理:要考虑输入中可能存在未配对的“enter”或“exit”记录,代码中通过合理的逻辑将这些未配对记录忽略,确保费用计算的准确性。
- 数据读取与存储:首先读取 24 个整数,存储到数组
- 1
信息
- ID
- 1648
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者