解题思路
这道题花了我很多时间,刷多了之后感觉相比树和图的题,这种细节比较多的题更难做一些,要想拿满分很不容易。
解这道题需要解决两个问题,一是怎么正确的找出一次通话的开始和结束的时间,解决的办法是把一个人的所有相关记录按照时间先后顺序排序,相邻的“on-line”和“off-line”即为一次通话,当然必须是“on-line”在前而“off-line”在后,这个问题和括号匹配很相似,所以我选择用栈来做;第二个问题是找到了一次通话的开始和结束时间之后怎么正确的计算该次通话的费用。这个问题我自己考虑的很复杂,最后是参考了柳神的代码,她的方法非常巧妙,首先计算从某月一号零点零分即01:00:00(dd:hh:mm)到打电话的时间需要的所有费用,然后再计算从01:00:00到挂断电话的时间需要的费用,二者之差即为此次通话的费用。这样就不用考虑打电话和挂电话是不是在同一时间段,有没有跨天等各种情况的差异,直接统一处理。具体实现请参考代码。
把我卡住的第三个问题就是,题目中没有明说,如果一个人没有合法的通话记录,那么不输出他的信息,而不是输出话费0,否则的话第二个和第三个测试点无法通过。另外,如果第四个测试点无法通过的话,说明你的代码没有正确处理通话时间跨天的问题。
AC代码
#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
struct node1{
string name;
int mon, day, hour, minute, time, tag;
};
vector<node1> record;
vector<int> rate(25);
int n;
bool cmp(node1 a, node1 b) {
return a.name != b.name ? a.name < b.name : a.time < b.time;
}
double cost(int d, int h, int m) {
double sum = 0;
sum += rate[h] * m + rate[24] * 60 * d;
for (int i = 0; i < h; i++) {
sum += rate[i] * 60;
}
return sum / 100.0;
}
void mbill() {
string s1 = record[0].name;
int i = 0;
double totalcost = 0.0;
stack<int> s;
vector<node1> ans;
while(i <= n) {
if ((i != n && record[i].name != s1) || i == n) {
if (!ans.empty()) {
cout << ans[0].name << " ";
printf("%02d\n", ans[0].mon);
for (int j = 1; j < ans.size(); j += 2) {
double p = cost(ans[j].day, ans[j].hour, ans[j].minute) - cost(ans[j - 1].day, ans[j - 1].hour, ans[j - 1].minute);
printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", ans[j - 1].day, ans[j - 1].hour, ans[j - 1].minute, ans[j].day, ans[j].hour, ans[j].minute, ans[j].time - ans[j - 1].time, p);
totalcost += p;
}
printf("Total amount: $%.2f\n", totalcost);
}
if (i == n) return;
s1 = record[i].name;
totalcost = 0.0;
while(!s.empty()) s.pop();
ans.clear();
}
if (record[i].tag == 1) {
while(!s.empty()) s.pop();
s.push(i);
} else {
if (!s.empty()) {
int v = s.top();
s.pop();
ans.push_back(record[v]);
ans.push_back(record[i]);
}
}
i++;
}
}
int main() {
for (int i = 0; i < 24; ++i) {
scanf("%d", &rate[i]);
rate[24] += rate[i];
}
scanf("%d", &n);
record.resize(n);
for (int i = 0; i < n; ++i) {
cin >> record[i].name;
scanf("%d:%d:%d:%d", &record[i].mon, &record[i].day, &record[i].hour, &record[i].minute);
string temp;
cin >> temp;
record[i].tag = (temp == "on-line")? 1 : 0;
record[i].time = record[i].day * 24 * 60 + record[i].hour * 60 + record[i].minute;
}
sort(record.begin(), record.end(), cmp);
mbill();
return 0;
}