题目说明:
输入:
24个小时每个时段通话价格 美分/分钟 toll[]
通话记录数N
N行通话记录:名字name 时间date 状态status (on-line表示通电话,off-line表示挂电话)
输出:每个客户的账单,按照客户名字的字典顺序输出,每个客户的多条记录按照时间顺序输出。on-line和off-line配对的才是有效记录。
注意点:若客户没有有效记录,则不打印这个客户的账单。
It is guaranteed that at least one call is well paired in the input. 保证至少有一条有效记录,但不是每个客户都有有效记录。
思路:先排序所有记录,按照姓名-时间升序排列,然后逐个计算每个客户的通话记录和话费。话费计算是先计算出从0时刻到通电话时刻的话费和到挂电话时刻的话费,两部分相减得到本条记录的话费。
代码:
#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
#define MAXN 1005
int toll[30];
int N;
int countdayprice();
struct Record{
string name;
string date;
int month;
int day;
int hour;
int min;
string status;
}record[MAXN];
bool cmp(const Record &a,const Record &b){
//以姓名排序,姓名相同以时间排序
if(a.name<b.name)
return true;
else if(a.name==b.name){
if(a.date<b.date)
return true;
else
return false;
}
else
return false;
}
int counttime(int s,int e){
int time;
time=record[e].day*60*24+record[e].hour*60+record[e].min
-(record[s].day*60*24+record[s].hour*60+record[s].min);
return time;
}
//计算从0到某个时间的总花费
int countprice(int day,int hour,int min){
int price=0;
for(int i=0;i<hour;i++){
price+=toll[i];
}
price*=60;
price+=toll[hour]*min;
price+=countdayprice()*day;
return price;
}
//计算每条记录的话费
float countrecordprice(int s,int e){
float price;
//结束减去开始
price=countprice(record[e].day,record[e].hour,record[e].min)-
countprice(record[s].day,record[s].hour,record[s].min);
return price/100;
}
//每天一整天的话费
int countdayprice(){
int dayprice=0;
for(int i=0;i<24;i++){
dayprice+=toll[i];
}
dayprice*=60;
return dayprice;
}
int main(){
#ifdef ONLINE_JUDGE
#else
ifstream cin("aa.txt");
#endif
for(int i=0;i<24;i++){
cin>>toll[i];
}
cin>>N;
for(int i=0;i<N;i++){
cin>>record[i].name>>record[i].date>>record[i].status;
string date=record[i].date;
record[i].month=(date[0]-48)*10+(date[1]-48);
record[i].day=(date[3]-48)*10+(date[4]-48);
record[i].hour=(date[6]-48)*10+(date[7]-48);
record[i].min=(date[9]-48)*10+(date[10]-48);
}
//排序所有记录。
sort(record,record+N,cmp);
string name="0";
int start;
int end;
float totalamount=0;
bool flagon=false;//on-off配对标记
bool flagname=false;//同一个用户的标记
for(int i=0;i<N;i++){
if(name!=record[i].name){
if(totalamount>0){
//输出总话费
printf("Total amount: $%.2f\n",totalamount);
}
name=record[i].name;
flagon=false;
flagname=false;
totalamount=0;
}
if(record[i].status=="on-line"){
start=i;
flagon=true;
}
else if(record[i].status=="off-line"){
if(flagon){
//输出name信息
if(!flagname){
flagname=true;
cout<<name;//string 用cout
printf(" %02d\n",record[i].month);
}
flagon=false;
end=i;
//输出一条记录
printf("%02d:%02d:%02d %02d:%02d:%02d ",
record[start].day,record[start].hour,record[start].min,
record[end].day,record[end].hour,record[end].min);
float recordprice=countrecordprice(start,end);
printf("%d $%.2f\n",counttime(start,end),
recordprice);
totalamount+=recordprice;
}
}
//最后一条记录的总话费输出
if(i==N-1&&totalamount>0)
printf("Total amount: $%.2f\n",totalamount);
}
return 0;
}
之前在排序记录的过程中出现了一些问题,开始是采用两次sort,先对时间进行排序,再对姓名进行排序,但是结果有时会出错。改了cmp函数用一次sort排序就可以了。后来发现sort是不稳定排序,如果要这样做必须用stable_sort进行稳定排序。
string类型只能用cin,cout,不能用scanf,printf ,若要用printf,只能用printf("%s",str.c_str())。