PAT (Advanced Level) 1016 Phone Bills——记录匹配+分段函数

题目传送门

这道题有几个关键点

记录匹配
  • 按时间排序后,每一个on-line记录与同名的最近的off-line记录匹配
    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.

之前我们似乎见过这样的题目描述方式嘛:异曲同工的记录匹配方法

结果记录

使用结构体记录匹配成功的通话记录
使用map将用户名映射到相应的编号上

struct node2 {
	char name[25];
	int cnt;
	int start[N];
	int end[N];
	int bill[N];
	int tot_bill;
};
node2 ans[N];
话费计算

我的想法是,设置一个信标按照小时移动
在这里插入图片描述

int cal_bill(int s, int t) {
	int ans = 0;
	int a = 0;
	for (int i = 0; ; ++i) {
		a += 60;
		if (a > s && a <= t) {
			ans += (a - s) * toll[i % 24];
			s = a;
		}
		if (a > t) {
			ans += (t - s) * toll[i % 24];
			break;
		}
	}
	return ans;
}
输出细节

输出时要注意补零,空格
话费要从美分转为美元

AC代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<string>
#include<algorithm>
using namespace std;

const int N = 1010;
map<string, int> myMap;
struct node {
	char name[25];
	int time;
	int flag;
};
node call[N];
int n,month;
int toll[30];
struct node2 {
	char name[25];
	int cnt;
	int start[N];
	int end[N];
	int bill[N];
	int tot_bill;
};
node2 ans[N];

int cmp(const node& A, const node& B) {
	return A.time < B.time;
}

int cmp2(const node2& A, const node2& B) {
	return strcmp(A.name, B.name) < 0;
}

int changeToFlag(char *s) {
	if (s[1] == 'n') return 0;
	else return 1;
}

int changeToTime(char* s) {
	int d = (s[3] - '0') * 10 + s[4] - '0';
	int h = (s[6] - '0') * 10 + s[7] - '0';
	int m = (s[9] - '0') * 10 + s[10] - '0';
	return d * 24 * 60 + h * 60 + m;
}

int cal_bill(int s, int t) {
	int ans = 0;
	int a = 0;
	for (int i = 0; ; ++i) {
		a += 60;
		if (a > s && a <= t) {
			ans += (a - s) * toll[i % 24];
			s = a;
		}
		if (a > t) {
			ans += (t - s) * toll[i % 24];
			break;
		}
	}
	return ans;
}

void prt_time(int t) {
	int d = t / (24 * 60);
	int h = (t % (24 * 60)) / 60;
	int m = t % 60;
	printf("%02d:%02d:%02d", d, h, m);
}

int main()
{
	for (int i = 0; i < 24; ++i) scanf("%d",&toll[i]);
	scanf("%d",&n);
	for (int i = 1; i <= n; ++i) {
		char a[25];
		char b[20];
		char c[20];
		scanf("%s%s%s",&a,&b,&c);
		strcpy(call[i].name, a);
		call[i].time = changeToTime(b);
		call[i].flag = changeToFlag(c);
		if (i == 1) month = (b[0] - '0') * 10 + b[1] - '0';
	}
	sort(call + 1, call + 1 + n, cmp);
	int cnt = 0;
	for (int i = 1; i < n; ++i) {
		if (call[i].flag == 0) {
			for (int j = i + 1; j <= n; ++j) {
				if (strcmp(call[i].name, call[j].name) == 0) {
					//只有可能与遇到的第一个有相同name的记录匹配
					if (call[j].flag == 1) {
						if (myMap[call[i].name] == 0) {
							myMap[call[i].name] = ++cnt;
							ans[cnt].cnt = 0;
							strcpy(ans[cnt].name, call[i].name);
						}
						int id = myMap[call[i].name];
						ans[id].cnt++;
						ans[id].start[ans[id].cnt] = call[i].time;
						ans[id].end[ans[id].cnt] = call[j].time;
						ans[id].bill[ans[id].cnt] = cal_bill(call[i].time, call[j].time);
						ans[id].tot_bill += ans[id].bill[ans[id].cnt];
					}
					break;
					//匹配不上
				}
			}
		}
	}
	sort(ans + 1, ans + 1 + cnt, cmp2);
	for (int i = 1; i <= cnt; ++i) {
		printf("%s %02d\n",ans[i].name,month);
		for (int j = 1; j <= ans[i].cnt; ++j) {
			prt_time(ans[i].start[j]);
			printf(" ");
			prt_time(ans[i].end[j]);
			printf(" %d $%0.2lf\n", ans[i].end[j] - ans[i].start[j],(double)ans[i].bill[j]/100.0);
		}
		printf("Total amount: $%0.2lf\n", (double)ans[i].tot_bill / 100);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值