PAT甲级1016,1017

1016

1016 Phone Bills (25 分)

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

题目大意:话费是按小时区段收的,然后告诉你各个小时区间每分钟的美分话费。然后一堆记录,记录了用户名,时间和通话还是离线。记录并不都是有效的,需要自己去筛选,然后按例子的模板打出这个月的账单就可以了。

扫描二维码关注公众号,回复: 3708394 查看本文章

解题思路:。。被这道题坑了半天,最后发现犯了个很弱智很弱智的错误。哎。

1.解决问题的方法其实无非就是下面几点,算出两个时间差距的分钟,算出两个时间之间通话的话费。这些都可以封装成一个函数。

2.然后是输出的格式,也许有人对这个01有疑问。其实不用管,无脑输出当前月就行了,因为题目说了。

3.然后是筛选出匹配的记录得到开始时间和结束时间。

这样三个解决了基本就没什么问题了。

第一个字符串处理一下就好了,计算话费就考虑一下是否同一天,如果同一天的话再考虑是否同一个小时,我的方法就是把头和尾去掉抽象成一个公式带进去算就行了。第二个就直接输出数组0的时间的前两位。第三个其实就是排个序,按人名字和时间升序排列一下,然后相邻两个名字相同,而且在线离线的属性正好前一个是on,后一个是off。

还有一个问题是得到总共几名顾客,这个在读入的时候用一下set就行了,当然注意的一点是set不用排序,自动排序去重的,很久没用我给忘了,然后过不去编译卡了会儿。

4.想了想我还是说一下我被坑的地方,万一有人和我一样傻逼呢。。我在匹配有效记录的时候,忘记写两个记录的用户名相同的判定条件了,结果死活就过了第一个测试点。

好了,代码如下。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
using namespace std;
struct Record {
	string name;
	string time;
	string flag;
};
struct signalRecord {
	string begintime;
	string endtime;
};
int Getmin(string a) {
	int dd = atoi(a.substr(3, 2).c_str());
	int hh = atoi(a.substr(6, 2).c_str());
	int mm = atoi(a.substr(9, 2).c_str());
	return (dd - 1) * 1440 + hh * 60 + mm;
}
bool Cmp(Record a, Record b) {
	if (a.name < b.name)return true;
	else if (a.name == b.name) {
		return Getmin(a.time) < Getmin(b.time);
	}
	else {
		return false;
	}
}
bool cmp(string a, string b) {
	return a < b;
}
double GetMoney(int *cost, string starttime,string endtime) {
	int dds = atoi(starttime.substr(3, 2).c_str());
	int hhs = atoi(starttime.substr(6, 2).c_str());
	int mms = atoi(starttime.substr(9, 2).c_str());
	int dde = atoi(endtime.substr(3, 2).c_str());
	int hhe = atoi(endtime.substr(6, 2).c_str());
	int mme = atoi(endtime.substr(9, 2).c_str());
	if (dds == dde) {
		if (hhs != hhe) {
			double sum = (60 - mms)*cost[hhs] + mme*cost[hhe];
			for (int i = hhs + 1; i < hhe; i++) {
				sum += 60 * cost[i];
			}
			return sum;
		}
		else {
				double sum = (mme - mms)*cost[hhs];
				return sum;
		}	
	}
	//01:00:01  02:00:01
	else {
		double sum = (60 - mms)*cost[hhs] + mme*cost[hhe];		
		for (int i = hhs + 1; i < 24; i++) {
			sum += 60 * cost[i];
		}
		for (int i = 0; i < hhe; i++) {
			sum += 60 * cost[i];
		}
		int dis = dde - dds-1;
		for (int i = 0; i < dis; i++) {
			for (int j = 0; j < 24; j++) {
				sum += 60 * cost[j];
			}
		}
		return sum;
	}
}
int main()
{
	int cost[25];
	for (int i = 0; i < 24; i++) {
		cin >> cost[i];
	}
	int n;
	cin >> n;
	Record cur[1005];
	set<string> Name;
	for (int i = 0; i < n; i++) {
		cin >> cur[i].name >> cur[i].time >> cur[i].flag;
		Name.insert(cur[i].name);
	}
	sort(cur, cur + n, Cmp);
	//for (int i = 0; i < n; i++) {
		//cout << cur[i].name << " " << cur[i].time << " " << cur[i].flag << endl;
	//}
	//sort(Name.begin(),Name.end(),cmp);
	for (auto i = Name.begin(); i != Name.end(); i++) {
		vector<signalRecord> PersonRecord;
		for (int j = 0; j < n - 1; j++) {
			if (cur[j].name == (*i) &&cur[j+1].name==(*i)&& cur[j].flag == "on-line"&&cur[j + 1].flag == "off-line") {
				signalRecord tmp;
				tmp.begintime = cur[j].time;
				tmp.endtime = cur[j + 1].time;
				PersonRecord.push_back(tmp);
			}
		}
		
		if (PersonRecord.size() != 0) {
			cout << (*i) << " ";
			cout << cur[0].time.substr(0, 2) << endl;
			double summoney = 0;
			for (auto q = PersonRecord.begin(); q != PersonRecord.end(); q++) {
				cout << (*q).begintime.substr(3, 8) << " " << (*q).endtime.substr(3, 8) << " " << Getmin((*q).endtime) - Getmin((*q).begintime);
				printf(" $%.2lf\n", GetMoney(cost, (*q).begintime, (*q).endtime) / 100.0);
				summoney += GetMoney(cost, (*q).begintime, (*q).endtime);
			}
			printf("Total amount: $%.2lf\n", summoney / 100.0);
		}
		else {
			continue;
		}
	}
	return 0;
}

1017 Queueing at Bank (25 分)

Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.

Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤10​4​​) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer. Here HH is in the range [00, 23], MM and SS are both in [00, 59]. It is assumed that no two customers arrives at the same time.

Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.

Output Specification:

For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.

Sample Input:

7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

Sample Output:

8.2

题目大意:相对上一题。。这题就比较水了,主要就是英文阅读里藏了个条件很坑。大概就是和银行排队一样,有一些窗口,然后一堆人。告诉你有几个窗口,然后每个顾客到达时间。计算一下平均等待时间。还有银行是8:00到17:00营业的,要注意是否超时。还有这里面有个条件,no more than 60min很坑,就是办业务的时间不能超过60min。

解题思路:其实很简单吧,全部变成秒单位,注意银行是可以早到,但不能迟到的。本来想用map或者queue,后来发现没什么必要,数组就足够了。窗口就是个int数组,顾客就是一个结构体数组,读的时候把17:00后的全部刷掉。也就是超过17*3600,的。然后把窗口的int数组初始化一下,初始化成开门时间,也就是8*3600.每次去找最早空闲的窗口。找到就更新一下窗口。如果没有空闲的窗口,那么找到等待时间最短的窗口,如果来早了就加上等待时间,不然就是更新一下窗口的下一次开放时间。

代码如下:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
using namespace std;
struct customer {
	int arrive;
	int time;
};
bool Cmp(customer a, customer b) {
	return a.arrive < b.arrive;
}
int main()
{
	int N, K;
	cin >> N >> K;
	vector<customer> cur;
	vector<int> windows;
	double costtime = 0;
	for (int i = 0; i < K; i++) {
		windows.push_back(8*3600);
	}
	for (int i = 0; i < N; i++) {
		string arr; int time;
		cin >> arr >> time;
		int arrtime = atoi(arr.substr(0, 2).c_str()) * 3600 + atoi(arr.substr(3, 2).c_str()) * 60 + atoi(arr.substr(6, 2).c_str());
		time = time > 60 ? 60 : time;
		if (arrtime > 17 * 3600)continue;
		customer tmp;
		tmp.arrive = arrtime;
		tmp.time = time*60;
		cur.push_back(tmp);
	}
	sort(cur.begin(), cur.end(), Cmp);
	for (int i = 0; i < cur.size(); i++) {
		int end = windows[0];
		int windowsindex = 0;
		for (int j = 1; j < K; j++) {
			if (windows[j] < end) {
				windowsindex = j;
				end = windows[j];
			}
		}
		if (cur[i].arrive < end) {
			costtime += (end - cur[i].arrive);
			windows[windowsindex] += cur[i].time;
		}
		else
			windows[windowsindex] = cur[i].arrive + cur[i].time;
	}
	if (cur.size() != 0)printf("%.1lf\n", costtime /cur.size()/60.0);
	else
		cout << "0.0" << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/TateBrwonJava/article/details/82953359