解题过程的小记录,如有错误欢迎指出。
题目分析
每个小时的电话费不同,给出打电话的记录,求出每位客户的电话账单进行输出。
注意点
- 间隔时间的分类计算,是否跨越天数,是否跨越小时数
- 1美元 = 100美分
我的解题过程
思路
采用record先进行数据的读入,然后对名字和时间进行排序后,为每个客户赋值对应的记录。
对我来说,本题的困难点在于:
- 数组的拆分,找到对应的通话记录,我通过一开始输入后就对客户和时间进行排序来解决
- 算出通话时间,采用了分支分类法,显得有点繁复,最后也是这里错了一处导致有一个测试点通过不了
bug
第一次提交代码后最后一个检测点没有通过,显示段错误,推测是fees[]数组相关语句的错误导致,经过检查,发现没有考虑到同一小时开始结束的情况,加入分支后得以解决
代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int fees[25];
struct record {
string name;
string time;
string condition;
int flag = 1;//如果为0就说明此条记录已经使用过,可以跳过
};
struct call {
string online;
string offline;
int fee;
};
struct person {
string name;
vector<call> calls;
};
int compare1(const record r1, const record r2) {
if (r1.name != r2.name)
return r1.name < r2.name;
else if (r1.time != r2.time)
return r1.time < r2.time;
else return 0;
}
double calculate(string online, string offline) {
cout << online << " " << offline;
int start_d = stoi(online.substr(0, 2));
int end_d = stoi(offline.substr(0, 2));
int start_h = stoi(online.substr(3, 2));
int end_h = stoi(offline.substr(3, 2));
int start_m = stoi(online.substr(6));
int end_m = stoi(offline.substr(6));
int totalmin = 0;
double result = 0;
if (start_h == end_h&&start_d == end_d) {//易错点:同个小时就不可以直接拿整个小时减去开始的分钟数
totalmin += end_m - start_m;
result = totalmin*fees[start_h];
}
else {
totalmin += 60 - start_m;
result += (60 - start_m)*fees[start_h];
start_h++;
if (start_h == 24) {
start_d++;
start_h = 0;
}
if (start_d == end_d) {
while (start_h != end_h) {
totalmin += 60;
result += 60 * fees[start_h];
start_h++;
}
totalmin += end_m;
result += end_m*fees[end_h];
}
else {
while (start_d != end_d) {
while (start_h != 24) {
totalmin += 60;
result += 60 * fees[start_h];
start_h++;
}
start_d++;
start_h = 0;
}
while (start_h != end_h) {
totalmin += 60;
result += 60 * fees[start_h];
start_h++;
}
totalmin += end_m;
result += end_m*fees[end_h];
}
}
printf(" %d $%.2lf\n", totalmin, result / 100.0);
return result / 100.0;
}
int main()
{
for (int i = 0; i < 24; i++) {
cin >> fees[i];
}
int N;
cin >> N;
vector<record> records;
vector<person> people;
for (int i = 0; i < N; i++) {
record r;
cin >> r.name >> r.time >> r.condition;
records.push_back(r);
}
sort(records.begin(), records.end(), compare1);
for (int i = 0; i < N; i++) {
if (records[i].flag == 0 || records[i].condition == "off-line") continue;
int j = 0;
for (j; j < people.size(); j++) {
if (records[i].name == people[j].name) break;
}
if (j == people.size()) {//此前没有此人的通话记录
call c;
c.online = records[i].time;
int k = i + 1;
for (k; k < N; k++) {
if (records[k].flag == 0) continue;
if (records[k].condition != "off-line") {
k = N;
break;
}
if (records[i].name == records[k].name&&records[k].condition == "off-line") {
c.offline = records[k].time;
break;
}
}
if (k != N) {
records[k].flag = 0;
person p;
p.name = records[i].name;
p.calls.push_back(c);
people.push_back(p);
}
}
else {//是people[j]的通话记录
call c;
c.online = records[i].time;
int k = i + 1;
for (k; k < N; k++) {
if (records[k].flag == 0) continue;
if (records[k].condition != "off-line") {
k = N;
break;
}
if (records[i].name == records[k].name&&records[k].condition == "off-line") {
c.offline = records[k].time;
break;
}
}
if (k != N) {
records[k].flag = 0;
people[j].calls.push_back(c);
}
}
records[i].flag = 0;
}
for (int i = 0; i < people.size(); i++) {
cout << people[i].name << " " << people[i].calls[0].online.substr(0, 2) << endl;
double total = 0;
for (int j = 0; j < people[i].calls.size(); j++) {
total += calculate(people[i].calls[j].online.substr(3), people[i].calls[j].offline.substr(3));
}
printf("Total amount: $%.2lf\n", total);
}
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 以下比较函数更为简洁
bool cmp(node a, node b) {
return a.name != b.name ? a.name < b.name : a.time < b.time;
}
- 设置一个变量保存打一天的花费,后序计算隔天时可以直接加上,顺便学习一下数组的初始化赋值方法
int rate[25] = {0};
for (int i = 0; i < 24; i++) {
scanf("%d", &rate[i]);
rate[24] += rate[i];
}
- 直接算出每个时间点到00:00:00的分钟数再两个进行相减
- 采用了map的键值对来对应每个客户的call
- 柳神的关于这题的代码还是有很多参考的地方,建议背诵全文(bushi)