【PAT-甲级】1016 Phone Bills

题目:

A long-distance telephone company charges its customers by the following rules:

Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connecting a long-distance call, the time will be recorded, and so will be the time when the customer hangs up the phone. Every calendar month, a bill is sent to the customer for each minute called (at a rate determined by the time of day). Your job is to prepare the bills for each month, given a set of phone call records.

Input Specification:

Each input file contains one test case. Each case has two parts: the rate structure, and the phone call records.

The rate structure consists of a line with 24 non-negative integers denoting the toll (cents/minute) from 00:00 - 01:00, the toll from 01:00 - 02:00, and so on for each hour in the day.

The next line contains a positive number N (≤1000), followed by N lines of records. Each phone call record consists of the name of the customer (string of up to 20 characters without space), the time and date (MM:dd:HH:mm), and the word on-line or off-line.

For each test case, all dates will be within a single month. Each on-line record is paired with the chronologically next record for the same customer provided it is an off-line record. Any on-line records that are not paired with an off-line record are ignored, as are off-line records not paired with an on-line record. It is guaranteed that at least one call is well paired in the input. You may assume that no two records for the same customer have the same time. Times are recorded using a 24-hour clock.

Output Specification:

For each test case, you must print a phone bill for each customer.

Bills must be printed in alphabetical order of customers' names. For each customer, first print in a line the name of the customer and the month of the bill in the format shown by the sample. Then for each time period of a call, print in one line the beginning and ending time and date (dd:HH:mm), the lasting time (in minute) and the charge of the call. The calls must be listed in chronological order. Finally, print the total charge for the month in the format shown by the sample.

Sample Input:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

Sample Output:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount: $28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount: $638.80

较为复杂繁琐的AC代码:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

struct peo
{
	string name;
	int month;
	int data;
	int hour;
	int minute;
	string state;
};
bool cmp(peo p1, peo p2)
{
	return p1.name != p2.name ? p1.name < p2.name : (p1.data != p2.data ? p1.data < p2.data 
		: (p1.hour != p2.hour ? p1.hour < p2.hour : (p1.minute < p2.minute)));
}
int main()
{
	int arr[24] = { 0 };
	for (int i = 0; i < 24; i++)
		cin >> arr[i];
	int n = 0;
	cin >> n;
	vector<peo> v;
	for (int i = 0; i < n; i++)
	{
		peo p;
		cin >> p.name;
		scanf("%02d:%02d:%02d:%02d", &p.month, &p.data, &p.hour, &p.minute);
		cin >> p.state;
		v.push_back(p);
	}
	sort(v.begin(), v.end(), cmp);
	vector<peo> v2;
	v2.push_back(v[0]);
	for (int i = 1; i < v.size(); i++)
	{
		if (v[i].name == v[i - 1].name)
		{
			v2.push_back(v[i]);
			if (i != v.size() - 1) /*!!!!*/
				continue;
		}
		//来到这里,表明此时v2中全是同一个人的内容

		double sum_price = 0.0;
		bool flag1 = true;
		for (int j = 0; j < v2.size(); j++)
		{
			if (/*!!!!*/ j!=v2.size()-1&& v2[j].state == "on-line" && v2[j + 1].state == "off-line")
			{
				double price = 0.0;
				int minute = 0;
				if (flag1 == true)   /*!!!!!*/
				{
					cout << v2[0].name << " ";
					printf("%02d\n", v2[0].month);
				}
				printf("%02d:%02d:%02d %02d:%02d:%02d ", v2[j].data, v2[j].hour, v2[j].minute, v2[j + 1].data, v2[j + 1].hour, v2[j + 1].minute);
				while (v2[j].data != v2[j + 1].data || v2[j].hour != v2[j + 1].hour || v2[j].minute != v2[j + 1].minute)
				{
					while (v2[j].minute != 60&&(v2[j].data != v2[j + 1].data || v2[j].hour != v2[j + 1].hour || v2[j].minute != v2[j + 1].minute))
					{
						price += arr[v2[j].hour];
						++v2[j].minute;  //分钟数加一
						++minute;
					}
					if(v2[j].data == v2[j + 1].data && v2[j].hour == v2[j + 1].hour && v2[j].minute == v2[j + 1].minute)/*!!!*/
						break;
					v2[j].minute = 0;
					++v2[j].hour;
					if (v2[j].hour == 24)
					{
						v2[j].hour = 0;
						++v2[j].data;
					}
				}
				sum_price += price;
				printf("%d $%.02lf\n", minute, price / 100.0);
				++j;/*!!!*/
				flag1 = false;
			}
		}
		if (sum_price)
		{
			printf("Total amount: $%.02lf\n", sum_price / 100.0);
		}
		//处理完这一个人之后
		v2.erase(v2.begin(), v2.end());
		v2.push_back(v[i]);
	}
	return 0;
}

1. 依旧是只用了vector和string。大致过程就是:先把数据存储起来,针对每个人的通话记录进行处理。我采用的方法是再创建一个vector来存储,(其实不是很方便的。)存储好之后再对这个人的数据进行处理。

2. 其中一个核心是:如何计算两个相邻时间时间的花销。这一部分我是直接模拟时间的增长来计算的,不够巧妙,其中也容易出错。(有几个地方都进行了改进)

3. 一个易错点是:若某人的数据中没有合理的时间,则这个人的信息不应该输出,因此引入了变量flag1

某柳姓玩家的代码:

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include<string>
using namespace std;
struct node {
    string name;
    int status, month, time, day, hour, minute;
};
bool cmp(node a, node b) {
    return a.name != b.name ? a.name < b.name : a.time < b.time;
}
double billFromZero(node call, int* rate) {
    double total = rate[call.hour] * call.minute + rate[24] * 60 * call.day;
    for (int i = 0; i < call.hour; i++)
        total += rate[i] * 60;
    return total / 100.0;
}
int main() {
    int rate[25] = { 0 }, n;
    for (int i = 0; i < 24; i++) {
        scanf("%d", &rate[i]);
        rate[24] += rate[i];
    }
    scanf("%d", &n);
    vector<node> data(n);
    for (int i = 0; i < n; i++) {
        cin >> data[i].name;
        scanf("%d:%d:%d:%d", &data[i].month, &data[i].day, &data[i].hour, &data[i].minute);
        string temp;
        cin >> temp;
        data[i].status = (temp == "on-line") ? 1 : 0;
        data[i].time = data[i].day * 24 * 60 + data[i].hour * 60 + data[i].minute;
    }
    sort(data.begin(), data.end(), cmp);
    map<string, vector<node> > custom;
    for (int i = 1; i < n; i++) {
        if (data[i].name == data[i - 1].name && data[i - 1].status == 1 && data[i].status == 0) {
            custom[data[i - 1].name].push_back(data[i - 1]);
            custom[data[i].name].push_back(data[i]);
        }
    }
    for (auto it : custom) {
        vector<node> temp = it.second;
        cout << it.first;
        printf(" %02d\n", temp[0].month);
        double total = 0.0;
        for (int i = 1; i < temp.size(); i += 2) {
            double t = billFromZero(temp[i], rate) - billFromZero(temp[i - 1], rate);
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", temp[i - 1].day, temp[i - 1].hour, temp[i - 1].minute, temp[i].day, temp[i].hour, temp[i].minute, temp[i].time - temp[i - 1].time, t);
            total += t;
        }
        printf("Total amount: $%.2f\n", total);
    }
    return 0;
}

 相比之下就好了很多,用了数据结构map

1.首先比较好的是相邻时间的费用的算法:比如5号12点到7号5点:则计算0号0点到这两个时间点之间的花销的差值即可,这也是引入rata[24]的原因。

2.将数据进行排序之后,一个难点就是如何将每个人的信息分开处理,甚至可以直接把合理的信息分开,不合理的舍弃(合理指的是第一个时间点为:on-line2第二个时间点为off-line)这里用的map就很好,map里的first是人名,second是这个人对应的合理的成对数据,用vector存储。如果某人没有合理的成对数据,则这个人的信息不会被录入到map中

3.最后遍历map,即对每个人进行处理,且这里面的数据一定是成对出现的合理数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值