题目大意:统计电话费用。一天24小时,给出每个小时内的电话费(cent/min)。之后给出N条通话记录,每条记录包括用户的姓名、记录时间和通话状态(on/off)。要求为每个用户都生成一份账单。值得注意的是, 对同一个用户而言,有效的通话记录是在时间上相邻的两条,前一条是on, 后一条是off。不满足这个条件的通话记录全部忽略。例如,某个用户的记录中, 6h01m 是on,5h59m也是on, 7h0m是off,那么有效的通话时间是 6h01m - 7h0m,因为它们在时间上相邻且状态不同。这一要求与PAT A1095 Cars on Campus 相同。
核心问题是如何得到每个用户的有效记录。这里需要将所有记录先按照用户姓名排序,再按时间排序。然后满足同一用户、时间相邻、状态不同的两条记录,才能被认为是有效的。之后就是繁琐的细节处理问题。
因为有天数的存在,计算账单时要考虑跨天,以及每个小时电话费用各不相同,所以直接用分钟为单位计算并不合适,考虑定义结构体记录时间信息。然后定义结构体记录客户信息,其中包括客户的on和off的时间序列。最后根据每个客户的on和off的时间序列,来计算时长和费用等等信息。涉及到时间的问题真的是非常繁琐。
AC代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstring>
using namespace std;
int price[24] = {0};
struct timeInfo
{
int month;
int day;
int hour;
int min;
timeInfo(int month, int day, int hour, int min): month(month), day(day), hour(hour), min(min){};
bool operator< (const timeInfo& another)
{
if(this->month != another.month) return this->month < another.month;
else if(this->day != another.day) return this->day < another.day;
else if(this->hour != another.hour) return this->hour < another.hour;
else return this->min < another.min;
}
};
struct record
{
string name;
timeInfo time;
int status;
record(string name, timeInfo time, int status): name(name), time(time), status(status){};
bool operator< (const record& another)
{
if(this->name != another.name) return this->name < another.name;
return this->time < another.time;
}
};
struct customer
{
string name;
int id;
vector<timeInfo> on;
vector<timeInfo> off;
customer(string name, int id, timeInfo on, timeInfo off)
{
this->name = name;
this->id = id;
this->on.push_back(on);
this->off.push_back(off);
}
};
map<string, int> nameToId;
int customerCount = 0;
int getId(string name)
{
if(nameToId.find(name) != nameToId.end()) return nameToId[name];
nameToId[name] = customerCount;
return customerCount++;
}
int calCost(const customer& c)
{
int totalCost = 0;
for (int i = 0; i < c.on.size(); ++i)
{
timeInfo on = c.on[i];
timeInfo off = c.off[i];
int totalMin = 0;
int cost = 0;
while(on.day != off.day || on.hour != off.hour || on.min != off.min)
{
on.min++;
cost += price[on.hour];
totalMin++;
if(on.min == 60)
{
on.min = 0;
on.hour++;
}
if(on.hour == 24)
{
on.hour = 0;
on.day++;
}
}
totalCost += cost;
printf("%02d:%02d:%02d ", c.on[i].day, c.on[i].hour, c.on[i].min);
printf("%02d:%02d:%02d ", c.off[i].day, c.off[i].hour, c.off[i].min);
printf("%d $%.2f\n", totalMin, cost * 1.0 / 100);
}
printf("Total amount: $%.2f\n", totalCost * 1.0 / 100);
}
int main()
{
for (int i = 0; i < 24; ++i)
{
scanf("%d", &price[i]);
}
int N;
cin >> N;
vector<record> all;
for (int i = 0; i < N; ++i)
{
char name[30], status[10];
int month, day, h, m;
scanf("%s %d:%d:%d:%d %s", name, &month, &day, &h, &m, status);
all.push_back(record(string(name), timeInfo(month, day, h, m), status[1] == 'n'? 1 : -1));
}
sort(all.begin(), all.end());
int index = 0;
vector<customer> vCustomer;
while(index < all.size() - 1)
{
if(all[index].name == all[index+1].name && all[index].status == 1 && all[index+1].status == -1)
{
int id = getId(all[index].name);
if(id == vCustomer.size())
{
vCustomer.push_back(customer(all[index].name, id, all[index].time, all[index+1].time));
}
else
{
vCustomer[id].on.push_back(all[index].time);
vCustomer[id].off.push_back(all[index+1].time);
}
index++;
}
index++;
}
for (int i = 0; i < vCustomer.size(); ++i)
{
printf("%s %02d\n", vCustomer[i].name.c_str(), vCustomer[i].on[0].month);
calCost(vCustomer[i]);
}
return 0;
}