PAT题解——1016. Phone Bills (25)

[声明]:由于本人在使用《算法笔记》的过程中有部分题解和《算法笔记》上的解法不同,特此作为记录,同时可以提供新的思路供读者参考;
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 %02d\n",re[i].name,re[i].mo);  //并判断本次有效配对的姓名和上次的是否相同; 
                strcpy(last_name,re[i].name);            
            }
            printf("%02d:%02d:%02d",re[i].dd,re[i].hh,re[i].mm);
            printf(" %02d:%02d:%02d",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; //总费用重新置零,用于下一个人的总费用计算 
        }
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值