[声明]:由于本人在使用《算法笔记》的过程中有部分题解和《算法笔记》上的解法不同,特此作为记录,同时可以提供新的思路供读者参考; 1. 题目链接:https://www.patest.cn/contests/pat-a-practise/1016 2. 解题思路: ① 用结构体存储姓名、月、日、时、分以及状态(0表示off-line,1表示on-line); ②对所有结构体数组内容进行排序,先按照姓名升序,使得相同姓名的排在一起,再按照通话时刻升序; ③对排好序的数组进行从头扫描,找出有效配对:即当前的姓名和下一个姓名相同,当前的状态为1,下一个状态为0;若不是有效配对,继续扫描; ④找到有效配对后,根据判断当前的姓名是否输出从而选择性输出姓名,再依次输出两个时刻,调用lasting函数计算并输出总持续时间,调用fee函数计算并输出对应时间段的费用;并加入total_amount; ⑤若当前姓名与下一个姓名不同,说明当前姓名total_amount已经计算完毕,输出即可; 3.AC代码:
#include<stdio.h> #include<cstring> #include<algorithm> using namespace std; const int maxn=1010; struct r{ char name[25]; int mo,dd,hh,mm; int status; //记录状态on-line或者off-line }re[maxn]; bool cmp(r a,r b){ if(strcmp(a.name,b.name)) return strcmp(a.name,b.name)<0; else if(a.dd!=b.dd) return a.dd<b.dd; else if(a.hh!=b.hh) return a.hh<b.hh; else return a.mm<b.mm; } int toll[24]; //用于存储一天中每个小时对应的费用 ,单位cent/min int lasting(int d,int h,int m,int dd,int hh,int mm){ //计算持续时间,d,h,m表示开始的日,时,分;dd,hh,mm表示结束时的日,时,分 int time=0; //记录持续的时间,单位:分 while(d!=dd||h!=hh||m!=mm){ //思路:通过不断将初始的m+1,同时time+1,最终和结束时间完全相同即可 ++m;++time; if(m==60){ m=0; ++h; } if(h==24){ h=0; ++d; } } return time; } double fee(int d,int h,int m,int dd,int hh,int mm){ //计算持续时间内的花费,d,h,m表示开始的日,时,分;dd,hh,mm表示结束时的日,时,分 double f=0; //记录话费 while(d!=dd||h!=hh||m!=mm){ ++m;f+=toll[h]; //加上对应小时的话费 if(m==60){ m=0; ++h; } if(h==24){ h=0; ++d; } } return f/100; //cent单位转换为$ } int main(){ int N; //总记录条数 for(int i=0;i<24;i++) scanf("%d",&toll[i]); //输入24小时对应的话费标准,单位cent/min scanf("%d",&N); char temp[10]; //临时记录"on-line"还是"off-line" for(int i=0;i<N;i++){ scanf("%s %d:%d:%d:%d %s",re[i].name,&re[i].mo,&re[i].dd,&re[i].hh,&re[i].mm,temp); if(!strcmp(temp,"on-line")) re[i].status=1; //若是on-line 则状态变为1,否则为0 else re[i].status=0; } sort(re,re+N,cmp); //总体进行排序,相同名字的排一起并升序,然后按照时间先后排序 char last_name[20]; //暂时不用理解 double total=0; //记录总话费 for(int i=0;i<N;i++){ if(strcmp(re[i].name,re[i+1].name)==0&&re[i].status==1&&re[i+1].status==0){ //有效配对 if(strcmp(re[i].name,last_name)){ //如果同名字的人有1对以上的有效配对 ,第二次不用输出姓名,所以用last_name存储上次输出的姓名 printf("%s d\n",re[i].name,re[i].mo); //并判断本次有效配对的姓名和上次的是否相同; strcpy(last_name,re[i].name); } printf("d:d:d",re[i].dd,re[i].hh,re[i].mm); printf(" d:d:d",re[i+1].dd,re[i+1].hh,re[i+1].mm); printf(" %d",lasting(re[i].dd,re[i].hh,re[i].mm,re[i+1].dd,re[i+1].hh,re[i+1].mm)); //调用函数计算持续时间,单位min double temp_fee=fee(re[i].dd,re[i].hh,re[i].mm,re[i+1].dd,re[i+1].hh,re[i+1].mm); //调用函数计算此时间段的费用,单位$ printf(" $%.2f\n",temp_fee); total+=temp_fee; //计算总费用 } if(strcmp(re[i].name,re[i+1].name)&&total){ //下一个名字不同,同时总费用不为0,则输出目前这个人的Total amount printf("Total amount: $%.2f\n",total); total=0; //总费用重新置零,用于下一个人的总费用计算 } } }