PAT甲级1016
简介:
单纯的模拟题,统计账单。
注意事项:
- 美分和美元的单位转换
- 去除无效的数据
对于无效数据,在输入时间的时候就按照从小到大的顺序来即可。那么,只要找到on-line和off-line这种匹配的,就算做有效,否则无效。
使用std::set
来作为人名的集合,使用list
来存储时间。因此熟练使用STL可以有较大的优势。
下面的代码在1和2测试点过不去,,,暂时没找到这两个神数据。。。。。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1003;
float price[24] = {0.0};
float day_cost = 0.0; // 一天的价格
const string online{"on-line"}, offline{"off-line"};
struct Tim {
string tim, line;
};
struct Person {
string name;
list<Tim>t;
int pos; // 位置顺序
bool operator==(const Person& tmp) {
return name == tmp.name;
}
Person(): pos(0) {}
} Per[MAXN];
struct cmp {
bool operator()(const Person &a, const Person &b) {
return a.name < b.name;
}
};
bool comp(const Person& p1, const Person p2) {
return p1.name < p2.name;
}
// 计算时间
int Time(const string& start, const string& stop) {
int day1, h1, m1, day2, h2, m2;
day1 = (start[3] - '0') * 10 + (start[4] - '0');
day2 = (stop[3] - '0') * 10 + (stop[4] - '0');
h1 = (start[6] - '0') * 10 + (start[7] - '0');
h2 = (stop[6] - '0') * 10 + (stop[7] - '0');
m1 = (start[9] - '0') * 10 + (start[10] - '0');
m2 = (stop[9] - '0') * 10 + (stop[10] - '0');
int sum = 0;
if(day1 < day2) { // 不是同一天
sum += (day2 - day1 - 1) * 24 * 60;
sum += (24 - h1 - 1) * 60 + (60 - m1) + h2 * 60 + m2;
} else { // 同一天
if(h1 == h2) { // 同一个小时
sum += m2 - m1;
} else { // 不同小时
sum += (h2 - h1 - 1) * 60 + (60 - m1) + m2;
}
}
return sum;
}
// 计算价格
float Bill(const string& start, const string& stop) {
int day1, h1, m1, day2, h2, m2;
day1 = (start[3] - '0') * 10 + (start[4] - '0');
day2 = (stop[3] - '0') * 10 + (stop[4] - '0');
h1 = (start[6] - '0') * 10 + (start[7] - '0');
h2 = (stop[6] - '0') * 10 + (stop[7] - '0');
m1 = (start[9] - '0') * 10 + (start[10] - '0');
m2 = (stop[9] - '0') * 10 + (stop[10] - '0');
float cost = 0.0;
if(day1 < day2) { // 不同天
cost += (day2 - day1 - 1) * day_cost;
for(int i = h1 + 1; i <= 23; ++i) {
cost += price[i] * 60;
}
cost += (60 - m1) * price[h1];
for(int i = 0; i < h2; ++i) {
cost += price[i] * 60;
}
cost += m2 * price[h2];
} else { // 同一天
if(h1 != h2) { // 不同小时
for(int i = h1 + 1; i < h2; ++i) {
cost += price[i] * 60;
}
cost += price[h1] * (60 - m1);
cost += price[h2] * m2;
} else { // 相同小时
cost += price[h1] * (m2 - m1);
}
}
return cost;
}
int main() {
set<Person, cmp>P; // 存储用户资料
for(int i = 0; i < 24; ++i) {
cin >> price[i];
price[i] /= 100.0;
}
for(int i = 0; i < 24; ++i) {
day_cost += price[i] * 60; // 一整天的话费
}
int N, M = 0; // N是输入个数,M是总共的人数
cin >> N;
while(N--) {
Person p;
Tim t;
cin >> p.name >> t.tim >> t.line;
auto it = P.find(p);
if(it == P.end()) { // 之前这人没出现过
p.pos = M; // 确定位置
p.t.push_back(t);
P.insert(p);
Per[M] = p;
++M;
} else { // 已经有人出现过了
auto i = Per[it->pos].t.begin();
for(; i != Per[it->pos].t.end(); i++) {
if(t.tim <= i->tim) {
Per[it->pos].t.insert(i, t); // 插入时间,时间肯定是从小到大排列的
break;
}
}
if(i == Per[it->pos].t.end()) {
Per[it->pos].t.push_back(t); // 时间最大,加入最后
}
}
}
sort(Per, Per + M, comp); // 字典序排序
for(int i = 0; i < M; ++i) {
string mon = Per[i].t.begin()->tim;
cout << Per[i].name << " " << mon[0] << mon[1] << endl; // 姓名 月份
float sum = 0.0;
for(auto it = Per[i].t.begin(); it != Per[i].t.end(); it++) {
it++;
auto it1 = it;
it--;
if(!(it->line == online && it1->line == offline)) { // 在线情况不匹配
continue;
}
float cost = Bill(it->tim, it1->tim);
sum += cost;
string s1(it->tim.begin() + 3, it->tim.end()), s2(it1->tim.begin() + 3, it1->tim.end());
cout << s1 << " " << s2 << " " << Time(it->tim, it1->tim) << " $";
printf("%.2f\n", cost);
it++;
}
printf("Total amount: $%.2f\n", sum);
}
return 0;
}