PAT-1016 Phone Bills (25)

题目大意:给定一天 24 小时的话费价格(注意给定的是一个小时内每分钟的价钱,美分计);然后给出 N 组用户通话记录(包括用户名、通话的时间日期、该时间段通话的状态),每个人的所有记录确保在同一个月内;输出每个人(按照用户名的字母顺序)的月账单,注意筛选规则(大致看样例):1.相邻时间段的“on-line”与“off-line”对应。2.最重要的一点是 如果某用户没有符合 1 条件的通话记录,则不输出用户的任何信息(否则测试组 2 、3 是没法通过的)。

注: 题目中 "It is guaranteed that at least one call is well paired in the input. "并没有保证每个用户都匹配成功,只是说所有用户中至少有一对是符合题意的。这很关键

解题思路:本题就是对数据的处理,相信看清了题目所要求的的细节,借助 C++ 强大的 stl (map、vector的使用),可以很快解决问题。

题目链接:https://www.patest.cn/contests/pat-a-practise/1016

#include <iostream>          
#include <algorithm>          
#include <set>          
#include <map>          
#include <vector>          
#include <stack>          
#include <queue>          
#include <cmath>          
using namespace std;

typedef struct Info{
	int month,day,hour,minute;
	string name;
	int time;
	int state;
}Info;//用户信息 
map<string,int> NameToNum;
map<int,string> NumToName;
vector<Info> info[1005];//用户信息存入 
int fee[24];
//对信息进行排序 
bool cmp(Info I1,Info I2)
{
	if(I1.time < I2.time)
		return true;
	return false;
}
 
int main(int argc, char** argv) {
	for(int i=0;i<24;++i)
	{
		int temp;
		cin >> temp;
		fee[i] = temp;//记录时段费用 
	}
	int n;
	string NameOrder[1005];//记录各用户名,方便字母顺序排序 
	cin >> n;
	int pos = 0;
	for(int i=0;i<n;++i)
	{
		string name,state;;
		int month,day,h,m;
		cin >> name;
		scanf("%d:%d:%d:%d",&month,&day,&h,&m);
		cin >> state;
		if(NameToNum.count(name) == 0)
		{
			NameOrder[pos] = name;
			NameToNum[name] = pos;//编号和用户名对应 
			NumToName[pos++] = name;
		}
		Info tmp;
		tmp.month = month;
		tmp.day = day;
		tmp.hour = h;
		tmp.minute = m;
		tmp.name = name;
		tmp.time = day*24*60+h*60+m; 
		if(state == "on-line")
			tmp.state = 0;
		else
			tmp.state = 1;
		info[NameToNum[name]].push_back(tmp);
	}
	sort(NameOrder,NameOrder+pos);
	for(int i=0;i<pos;++i)
		sort(info[i].begin(),info[i].end(),cmp);//单一用户名进行时间排序 
	for(int i=0;i<pos;++i)
	{
		double sum = 0;
		int id = NameToNum[NameOrder[i]];
		vector<Info>::iterator it = info[id].begin();
		int flag = 0; 
		for(;it != info[id].end();++it)
		{
			if(it->state == 0 && (it+1) != info[id].end() && (it+1)->state ==1)
			{
				flag = 1;//判断是否有有效通话时间段,如果没有,则什么也不输出 
			} 
			
		}
		if(flag == 0)
			continue;
		//输出用户信息 
		it = info[id].begin();
		cout << NameOrder[i] ;//<< info[id].;
		printf(" %02d\n",it->month);
		for(;it != info[id].end();++it)
		{
			double sum1 = 0;
			//满足用户通话需求 
			if(it->state == 0 && (it+1) != info[id].end() && (it+1)->state ==1)
			{
				printf("%02d:%02d:%02d ",it->day,it->hour,it->minute);
				printf("%02d:%02d:%02d ",(it+1)->day,(it+1)->hour,(it+1)->minute);
				int tol = (it+1)->time - it->time;
				printf("%d ",tol);
				int h = it->hour;
				int m = it->minute;
				//模拟时间,计算费用 
				while(1)
				{
					sum1 += fee[h];
					//cout<<h<<endl;
					if(m == 59)
					{
						m = 0;
						if(h == 23)
							h = 0;
						else
							++h;
					}
					else
						m++;
					if(--tol == 0)
						break;
				}
				sum += sum1;
				printf("$%.2f\n",sum1/100.0);
			}
			
		}
		printf("Total amount: $%.2f\n",sum/100.0);
	}
	
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值