1016 Phone Bills (25 分)

算法核心:
每小时对应一个费率,统计在一段时间内的费用;
拆成秒的模式,在每一个时间段逐项相加;(由于这道题和小时相关,所以不拆成秒数相加的形式可能更好做)
个人觉得当时的做法挺麻烦的,以后有时间了再优化吧

AC CODE:

#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
using namespace std;
const int maxn = 1010;

int rate[24];
struct REC{
    string name;
    int time,statu,month;
}rec[maxn];

struct PER_REC{
    pair<int,int> time_rec;
    int minute,cost,month;
    PER_REC(){
        cost = 0;
    }
};
map<string,vector<PER_REC> > mp;

bool cmp(REC a,REC b){
    if(a.name!=b.name) return a.name < b.name;
    else return a.time<b.time;
}

int n,month,sum_rate = 0;
int main() {
    int sum=0;
    for(int i=0;i<24;i++){
        scanf("%d",&rate[i]);
        sum+=rate[i];//sum是一整天的费率
        sum_rate += rate[i]*60;
    }
    cin >> n;
    for(int i=0;i<n;i++){
        string statu;
        int m,d,h,mi;
        cin >> rec[i].name;
        scanf("%d:%d:%d:%d",&m,&d,&h,&mi);
        month = m;
        cin >> statu;
        rec[i].statu = statu=="on-line"?1:0;
        rec[i].time = d*24*60+h*60+mi;
        rec[i].month = month;
    }
    sort(rec,rec+n,cmp);
    for(int i=0;i<n-1;i++){
        if(rec[i].name!=rec[i+1].name || !(rec[i].statu==1 && rec[i+1].statu==0)) continue;//名字不一样或者状态不对就跳过
        PER_REC tmp;
        tmp.time_rec = {rec[i].time,rec[i+1].time};
        tmp.minute = rec[i+1].time - rec[i].time;//统计这一对记录有多少分钟
        tmp.month = rec[i].month;//因为题目局限在一个月内
        int a = rec[i].time,b = rec[i+1].time;
        while(a<b){//***这一段是对费用进行累加的核心
            int index = a%1440/60;//代表通话的起始时间的费率下标
            int up = a/1440*1440+(index+1)*60>b?b:a/1440*1440+(index+1)*60;//到下一个时间点的分钟数
            int sum = rate[index] * (up-a);//两段之间的分钟数总和
            tmp.cost += rate[index] * (up-a);//计算这一个时间段有多少费用
            a = up;//更新起始时间到新的一段去
        }
        mp[rec[i].name].push_back(tmp);
    }
    for(auto it:mp){
        double sum = 0;
        printf("%s",it.first.c_str());
        vector<PER_REC> tmp = it.second;
        printf(" %02d\n",tmp[0].month);
        for(auto it1:tmp){
            int time1 = it1.time_rec.first,time2 = it1.time_rec.second;
            printf("%02d:%02d:%02d",time1/60/24,time1%(24*60)/60,time1%(24*60)%60);
            printf(" %02d:%02d:%02d",time2/60/24,time2%(24*60)/60,time2%(24*60)%60);
            printf(" %d $%.2f\n",it1.minute,it1.cost*1.0/100);
            sum += it1.cost*1.0/100;
        }
        printf("Total amount: $%.2f\n",sum);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值