停车场收入统计
题目描述
给定一个停车场某一天的车辆出入记录,请计算该停车场的当日收入,收费规则如下:
- 停车半小时收费 1 元,不足半小时按半小时计算。
- 一辆车每天收费封顶 15 元。
- 停车时间小于半小时则不收费。
- 11:30 - 13:30 不计入停车时间。
- 包月的车辆不统计当日收入。
输入描述
第一段是购买了包月服务的车辆信息:第一行是包月车辆的数量;从第二行开始,每行是一个包月的车牌号。 第二段是当日车辆出入记录:格式为:时 (24 小时制):分 车牌号(6~10 位)enter/leave
输出描述
停车场当日收入,整数。
备注
假设所有车辆在当天进当天离。每天的车辆出入记录<10000 条,包月车辆个数小于 10000。
解题思路
- 数据预处理:读取包月车辆列表存入集合以便快速查询。
- 记录匹配:遍历出入记录,将同一车牌号的进入和离开记录配对。
- 时长计算:计算两时间点的时间差,扣除 11:30 至 13:30 之间的时段。
- 若停车跨越该时段,需分段计算有效时长。
- 费用计算:
- 有效时长不足 30 分钟免费。
- 否则向上取整到 0.5 小时单位,乘以 1 元。
- 单辆车单日累计不超过 15 元。
- 汇总:累加所有非包月车辆的最终费用。
代码实现 (Python)
import sys
from datetime import datetime
def parse_time(t_str):
h, m = map(int, t_str.split(':'))
return h * 60 + m
def get_overlap(start, end):
# 11:30 = 690, 13:30 = 810
exclude_start, exclude_end = 690, 810
if start >= exclude_end or end <= exclude_start:
return 0
return min(end, exclude_end) - max(start, exclude_start)
def solve():
lines = sys.stdin.read().strip().split('\n')
idx = 0
# 读取包月车辆
try:
monthly_count = int(lines[idx])
idx += 1
monthly_plates = set()
for _ in range(monthly_count):
monthly_plates.add(lines[idx].strip())
idx += 1
except IndexError:
print(0)
return
records = []
while idx < len(lines):
parts = lines[idx].strip().split()
if len(parts) < 3:
break
time_str, plate, action = parts[0], parts[1], parts[2]
records.append((time_str, plate, action))
idx += 1
# 按车牌分组
car_events = {}
for t, p, a in records:
if p in monthly_plates:
continue
if p not in car_events:
car_events[p] = []
car_events[p].append((parse_time(t), a))
total_income = 0
for plate, events in car_events.items():
events.sort(key=lambda x: x[0])
daily_fee = 0
i = 0
while i < len(events) - 1:
start_time, enter_action = events[i]
end_time, leave_action = events[i+1]
if enter_action == 'enter' and leave_action == 'leave':
duration = end_time - start_time
overlap = get_overlap(start_time, end_time)
effective_duration = max(0, duration - overlap)
if effective_duration > 0:
fee_units = (effective_duration + 29) // 30
fee = min(fee_units, 15)
daily_fee += fee
i += 2
else:
i += 1
total_income += daily_fee
print(total_income)
if __name__ == "__main__":
solve()
代码实现 (C++)
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
int parseTime(string t) {
int h = stoi(t.substr(0, 2));
int m = stoi(t.substr(3, 2));
return h * 60 + m;
}
int main() {
int n;
cin >> n;
set<string> monthly;
for (int i = 0; i < n; ++i) {
string plate; cin >> plate;
monthly.insert(plate);
}
vector<pair<int, pair<string, string>>> records;
string t, plate, action;
while (cin >> t >> plate >> action) {
if (monthly.count(plate)) continue;
records.push_back({parseTime(t), {plate, action}});
}
sort(records.begin(), records.end());
long long total = ;
i = ;
(i < records.() - ) {
string p1 = records[i].second.first;
string p2 = records[i].second.first;
(p1 == p2 && records[i].second.second == && records[i].second.second == ) {
start = records[i].first;
end = records[i].first;
overlap = ;
exS = *, exE = *;
(start < exE && end > exS)
overlap = (end, exE) - (start, exS);
eff = (, end - start - overlap);
(eff > ) {
units = (eff + ) / ;
total += (units, );
}
i += ;
} {
i++;
}
}
cout << total << endl;
;
}
示例说明
输入:
1
A12345
10:00 A12345 enter
12:00 A12345 leave
14:00 B67890 enter
15:00 B67890 leave
输出:
2
解释:A12345 为包月车不计费。B67890 停车 1 小时,扣除 11:30-13:30 中的重叠部分(若有),按半小时计费。


