PAT甲级 1016 Phone Bills(时间差)

Link

题意:

远程电话的收费是按照每分钟来计费的,现在告诉你一天24小时中每分钟的收费标准,以及n条通话记录,试求出每个人该月的消费账单。

只有开始记录没有结束记录的通话不计费,反之亦然。保证所有消费记录在同一个月,且至少含有一条满足计费的账单记录。

输出是需要输出用户姓名,月份,每一条记录的开始结束时间于计费,总计费。按照用户名升序输出账单。

思路:

常规的一个时间差计算题,但是该题细节较多,也有许多坑点。先按照用户名升序,再按照时间升序来排序。再依次处理每次完整的通话。

刚开始是考虑前缀和直接获取时间段对应的计费,但是已知过不了1、2测试点。

坑点:没有完整消费记录的用户不用输出账单,虽然我跳过了这个坑,但是为注意自己的”Total amount: $“是在判断以外输出的,这会导致无消费的账单同样有这句输出。

后来换了一个直接计算的思路,最后发现是输出的锅,哎~.

前缀和的代码:

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 6e5+10;

int c[25];
int n, tt;
int s[N], pre[N];
string na, tmp, line, month;
map<string, int> vis;

struct node{
    string name;
    string time;
    int tag;
    int tm;
}r[N];

int get_int(char x){
    return x-'0';
}

int trans(string s){
    int res = get_int(s[0])*10+get_int(s[1]);
    res *= 24;
    res += get_int(s[3])*10+get_int(s[4]);
    res *= 60;
    res += get_int(s[6])*10+get_int(s[7]);
    return res;
}

bool cmp(node a, node b){
    if(a.name==b.name) return a.tm<b.tm;
    return a.name<b.name;
}

signed main()
{
    for(int i = 0; i < 24; i ++){
        cin >> c[i];
        for(int j = 1; j <= 60; j ++){
            s[++tt] = c[i];
            pre[tt] = pre[tt-1]+c[i];
        }
    }
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> na >> tmp >> line;
        r[i].name = na;
        r[i].time = tmp.substr(3, 8);
        r[i].tm = trans(r[i].time);
        if(line[1]=='n') r[i].tag = 1;
        else r[i].tag = 2;
        if(month.size()==0) month = tmp.substr(0, 2);
    }
    sort(r+1, r+n+1, cmp);

    for(int i = 1; i <= n; i ++){
        if(!vis[r[i].name]){
            na = r[i].name;
            vis[na] ++;
            double tot = 0;
            bool flag = 0;
            for(int j = i; j < n; j ++){
                if(r[j].tag==1 && r[j+1].tag==2 && r[j+1].name==r[j].name){
                    if(vis[r[j].name]==1){
                        cout << na << " " << month << endl;
                        vis[na] ++;
                    }
                    double cost = 0;
                    int rep = get_int(r[j].time[0])*10+get_int(r[j].time[1]);
                    rep *= 24*60;
                    if(r[j].time.substr(0, 2) == r[j+1].time.substr(0,2)){
                        cost = pre[r[j+1].tm-rep]-pre[r[j].tm-rep];
                    }
                    else{
                        cost += pre[24*60]-pre[r[j].tm-rep];
                        int days = stoi(r[j+1].time.substr(0,2))-stoi(r[j].time.substr(0, 2))-1;
                        cost += days*pre[24*60];
                        int rep1 = get_int(r[j+1].time[0])*10+get_int(r[j+1].time[1]);
                        rep1 *= 24*60;
                        cost += pre[r[j+1].tm-rep1];
                    }
                    tot += cost*0.01;
                    cout << r[j].time << " " << r[j+1].time << " " << r[j+1].tm-r[j].tm << " $";
                    cout << fixed << setprecision(2) << cost*0.01 << endl;
                    flag = 1;
                }
                if(r[j+1].name!=na){
                    i = j-1;
                    break;
                }
            }
            if(flag) cout << "Total amount: $" << tot << endl;
        }
    }

    return 0;
}

直接计算的代码:

#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int N = 6e5+10;

int c[25], sum;
int n, tt;
int s[N], pre[N];
string na, tmp, line, month;
map<string, int> vis;

struct node{
    string name;
    string time;
    int tag;
    int tm;
}r[N];

int get_int(char x){
    return x-'0';
}

int trans(string s){
    int res = get_int(s[0])*10+get_int(s[1]);
    res *= 24;
    res += get_int(s[3])*10+get_int(s[4]);
    res *= 60;
    res += get_int(s[6])*10+get_int(s[7]);
    return res;
}

bool cmp(node a, node b){
    if(a.name==b.name) return a.tm<b.tm;
    return a.name<b.name;
}

int get_difference(string ed, string bg){
    int res = 0;
    int day0 = stoi(bg.substr(0,2)), day1 = stoi(ed.substr(0,2));
    int hour0 = stoi(bg.substr(3,2)), hour1 = stoi(ed.substr(3,2));
    int minute0 = stoi(bg.substr(6,2)), minute1 = stoi(ed.substr(6,2));
    if(day0==day1){  // 同一天
//        cout << "同一天" << endl;
        if(hour0==hour1){  // 同一小时
            res += (minute1-minute0)*c[hour0];
//            cout << "同一小时 -> res: " << res << endl;
        }else{  // 不同小时
//            cout << "不同小时:" << endl;
            res += (60-minute0)*c[hour0];
//            cout << "加上开始剩余分钟的 -> res: " << (60-minute0)*c[hour0] << endl;
            for(int i = hour0+1; i < hour1; i ++) res += 60*c[i];
//            cout << "加上中间小时的 -> res: " << res << endl;
            res += minute1*c[hour1];
//            cout << "加上结束剩余分钟的 -> res: " << res << endl;
        }
    }else{
//        cout << "不同天" << endl;
        res += (60-minute0)*c[hour0];
//        cout << "加上开始剩余分钟的 -> res: " << res << endl;
        for(int i = hour0+1; i < 24; i ++){  // 开始当天的消费
            res += 60*c[i];
        }
//        cout << "加上开始剩余小时的 -> res: " << res << endl;
        res += (day1-day0-1)*sum;  // 中间几天的消费
//        cout << "加上中间" << (hour1-hour0-1) << "天的 -> res: " << res << endl;
        for(int i = 0; i < hour1; i ++){
            res += 60*c[i];
        }
//        cout << "加上结束剩余小时的 -> res: " << res << endl;
        res += minute1*c[hour1];  // 结束当天的消费
//        cout << "加上结束剩余分钟的 -> res: " << res << endl;
    }
    return res;
}

signed main()
{
    for(int i = 0; i < 24; i ++){
        cin >> c[i];
        sum += c[i]*60;
    }
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> na >> tmp >> line;
        r[i].name = na;
        r[i].time = tmp.substr(3, 8);
        r[i].tm = trans(r[i].time);
        if(line[1]=='n') r[i].tag = 1;
        else r[i].tag = 2;
        if(month.size()==0) month = tmp.substr(0, 2);
    }
    sort(r+1, r+n+1, cmp);

    for(int i = 1; i <= n; i ++){
        if(!vis[r[i].name]){
            na = r[i].name;
            vis[na] ++;
            double tot = 0;
            bool flag = 0;
            for(int j = i; j < n; j ++){
                if(r[j].tag==1 && r[j+1].tag==2 && r[j+1].name==r[j].name){
                    if(vis[r[j].name]==1){
                        cout << na << " " << month << endl;
                        vis[na] ++;
                    }
                    double cost = get_difference(r[j+1].time, r[j].time);
                    tot += cost*0.01;
                    cout << r[j].time << " " << r[j+1].time << " " << r[j+1].tm-r[j].tm << " $";
                    cout << fixed << setprecision(2) << cost*0.01 << endl;
                    flag = 1;
                }
                if(r[j+1].name!=na){
                    i = j-1;
                    break;
                }
            }
            if(flag) cout << "Total amount: $" << tot << endl;
        }
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值