PAT甲题题解-1016. Phone Bills (25)-模拟、排序

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~
http://www.cnblogs.com/chenxiwenruo/p/6789229.html
特别不喜欢那些随便转载别人的原创文章又不给出链接的
所以不准偷偷复制博主的博客噢~~

给出一天24小时内,每个小时内,每分钟的通话费用
给出n个记录,on-line表示通话的开始,off-line表示通话的结束
如果on-line/off-line没有对应的另一个,忽略即可

先按人名排序,名称一样的按时间排序,这里时间统一按分钟来算,即一天有24*60分钟,那么01:01:05就是0*24*60+1*60+5
然后找出彼此配对的on-line和off-line,存入phone数组
然后接下来就是求出每个通话时间的费用即可

(主要是如何计算出费用比较细节麻烦一点,推荐做一下)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ONLINE 0
#define OFFLINE 1
using namespace std;
const int maxn=1000+5;
const int DAYMINUTE=24*60;
const int HOURMINUTE=60;
int toll[24];
int n;
struct Record{
    char name[25];
    int time;
    int month;
    int day;
    int hour;
    int minute;
    int mark;
    bool operator<(const Record tmp)const{
        if(strcmp(name,tmp.name)==0)
            return time<tmp.time;
        else if(strcmp(name,tmp.name)<0)
            return true;
        else
            return false;
    }
}record[maxn];

struct Phone{
    char name[25];
    int month;
    int d1,h1,m1;
    int d2,h2,m2;
    int time1,time2;
}phone[maxn];
int cnt=0;
/**
求出第i个配对的通话时间费用
*/
int cal(int i){
    int sum=0;
    int start=phone[i].time1; //起始时间
    int ends=phone[i].time2;  //结束时间
    int tmp=0; //统计每个小时的时间段内,通话的分钟
    int idx; //对应时间段toll的索引
    for(int t=start;t<=ends;t++){
        if(t%60==0){
            if(t%DAYMINUTE==0)
                idx=(DAYMINUTE-1)/60;  //如果模为0,就应该是DAYMINUTE
            else
                idx=(t%DAYMINUTE-1)/60; //因为可能会有连续通话了好几天,所以得取模一下
            sum+=tmp*toll[idx];  //通话的分钟*该时间段的费用
            tmp=1; //为了方便起见,像01:06:00这种整时的,算作下一小时的
        }
        else
            tmp++;
    }
    if(tmp){
        //比如说1:08:03,由于1:08:00的时候算作8-9之间的,实际上统计的tmp=4,所以要-1
        sum+=(tmp-1)*toll[(ends%DAYMINUTE)/60];
    }
    return sum;
}
int main()
{
    char word[10];
    for(int i=0;i<24;i++)
        scanf("%d",&toll[i]);
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s %d:%d:%d:%d %s",record[i].name,&record[i].month,&record[i].day,&record[i].hour,&record[i].minute,word);
        record[i].time=(record[i].day-1)*DAYMINUTE+record[i].hour*HOURMINUTE+record[i].minute;
        if(word[1]==‘n‘)
            record[i].mark=ONLINE;
        else
            record[i].mark=OFFLINE;
    }
    sort(record,record+n);
    int last=-1; //之前最近的一个on-line的索引
    //找出配对的on-line和off-line,存入phone数组,方便后序处理
    for(int i=0;i<n;i++){
        if(record[i].mark==ONLINE){
            last=i;
        }
        if(record[i].mark==OFFLINE && last!=-1){
            if(strcmp(record[i].name,record[last].name)==0){
                strcpy(phone[cnt].name,record[i].name);
                phone[cnt].month=record[i].month;
                phone[cnt].d1=record[last].day;
                phone[cnt].h1=record[last].hour;
                phone[cnt].m1=record[last].minute;
                phone[cnt].time1=record[last].time;
                phone[cnt].d2=record[i].day;
                phone[cnt].h2=record[i].hour;
                phone[cnt].m2=record[i].minute;
                phone[cnt].time2=record[i].time;
                cnt++;
                last=-1;
            }
        }
    }
    int tot=0,sum=0;
    for(int i=0;i<cnt;i++){
        if(i==0){
            printf("%s %02d\n",phone[i].name,phone[i].month);
            sum=cal(i);
            tot+=sum;
            int len=phone[i].time2-phone[i].time1;
            double cost=sum*1.0/100;
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",phone[i].d1,phone[i].h1,phone[i].m1,phone[i].d2,phone[i].h2,phone[i].m2,len,sum*1.0/100);
        }
        else{
            if(strcmp(phone[i].name,phone[i-1].name)!=0){
                printf("Total amount: $%.2lf\n",tot*1.0/100);
                printf("%s %02d\n",phone[i].name,phone[i].month);
                tot=0;
            }
            sum=cal(i);
            tot+=sum;
            int len=phone[i].time2-phone[i].time1;
            int cost=sum*1.0/100;
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",phone[i].d1,phone[i].h1,phone[i].m1,phone[i].d2,phone[i].h2,phone[i].m2,len,sum*1.0/100);
        }
    }
    if(tot){
        printf("Total amount: $%.2lf\n",tot*1.0/100);
    }
    return 0;
}

时间: 2024-10-11 06:19:52

PAT甲题题解-1016. Phone Bills (25)-模拟、排序的相关文章

PAT甲题题解-1101. Quick Sort (25)-大水题

快速排序有一个特点,就是在排序过程中,我们会从序列找一个pivot,它前面的都小于它,它后面的都大于它.题目给你n个数的序列,让你找出适合这个序列的pivot有多少个并且输出来. 大水题,正循环和倒着循环一次,统计出代码中的minnum和maxnum即可,注意最后一定要输出'\n',不然第三个测试会显示PE,格式错误. #include <iostream> #include <cstdio> #include <algorithm> #include <map&

PAT甲题题解-1130. Infix Expression (25)-中序遍历

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789828.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~~ 水,中序遍历输出即可注意除根节点.叶子节点外,都需要有括号括起来 #include <iostream> #include <cstdio> #include <algorithm> #include <string>

PAT甲题题解-1051. Pop Sequence (25)-堆栈

将1~n压入最多为m元素的栈 给出k个出栈序列,问你是否能够实现. 能输出YES 否则NO 模拟一遍即可,水题. #include <iostream> #include <cstdio> #include <string.h> #include <algorithm> using namespace std; const int maxn=1005; int m,n,k; int seq[maxn]; int stacks[maxn]; int rear=

PAT甲题题解-1114. Family Property (25)-(并查集模板题)

题意:给出每个人的家庭成员信息和自己的房产个数与房产总面积,让你统计出每个家庭的人口数.人均房产个数和人均房产面积.第一行输出家庭个数,随后每行输出家庭成员的最小编号.家庭人口数.人均房产个数.人均房产面积. 并查集,合并的时候编号小的作为父亲节点,最后父亲节点一样的即属于一个家庭,其它都是细节处理没啥好说了. #include <iostream> #include <cstdio> #include <algorithm> #include <string.h

PAT甲题题解-1121. Damn Single (25)-水题

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789787.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~~ 给出n个couple和m个宾客如果宾客没有couple或者couple没来,则被认为lonely问你有多少个lonely的宾客,并且按照id的升序输出 #include <iostream> #include <cstdio> #include

PAT甲题题解-1109. Group Photo (25)-(模拟拍照排队)

题意:n个人,要拍成k行排队,每行 n/k人,多余的都在最后一排. 从第一排到最后一排个子是逐渐增高的,即后一排最低的个子要>=前一排的所有人 每排排列规则如下: 1.中间m/2+1为该排最高: 2.其他人按各自降序顺序,轮流排到中间最高的左边和右边: 举个例子 190 188 186 175 170 - - 190 - - - 188 190 - - - 188 190 186 - 175 188 190 186 - 175 188 190 186 170 3.当个子一样高时,名字按字典序顺序

PAT甲题题解-1037. Magic Coupon (25)-贪心,水

题目说了那么多,就是给你两个序列,分别选取元素进行一对一相乘,求得到的最大乘积. 将两个序列的正和负数分开,排个序,然后分别将正1和正2前面的相乘,负1和负2前面的相乘,累加和即可. #include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <cmath> #include <vector> using namespa

PAT甲题题解-1088. Rational Arithmetic (20)-模拟分数计算

输入为两个分数,让你计算+,-,*,\四种结果,并且输出对应的式子,分数要按带分数的格式k a/b输出如果为负数,则带分数两边要有括号如果除数为0,则式子中的结果输出Inf模拟题最好自己动手实现,考验细节处理,其它没啥好说的. #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; long long numerato

PAT甲题题解-1042. Shuffling Machine (20)-模拟

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789205.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~ 给出洗牌次数,以及洗牌的序列规则第i个数shuffles[i]表示要将第i张牌移到第shuffles[i]个 很简单,就是shuffle_seq[shuffles[i]]=start_seq[i]; #include <iostream> #include