PAT 甲级 1016 Phone Bills.[模拟排序]

题意:
1. 先给了 24 24 个数表示 24 24 小时每个小时内通话的费用, 单位为 分/分钟
2. 给了 N(1000) N ( ≤ 1000 ) 条记录,记录格式为 [姓名][月:日:小时:分钟][on/off-line], 表示这个人在这个时间开始/结束通话。对于同一个人,每个开始通话记录与在它之后时间最近的结束通话记录相匹配,结束通话记录同理,一对匹配构成一次通话,若没有匹配的则忽略。
3. 按照格式要求输出每个人的账单。

分析:按照题意模拟即可

坑点:
1. 每个人的账单的输出顺序按照字典序输出。
2. 每个人的账单内的通话记录需按照时间顺序输出。
3. 如果一个人的账单内没有通话记录,那他什么都不输出,直接跳过。

#include <bits/stdc++.h>
using namespace std;
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1
typedef long long ll;

const int inf = 0x3f3f3f3f;

const int MAXN = 1005;
const int MAXM = 100000 + 10;

struct record {
    string name;
    int mm, dd, hh, minute, type;
    // 按照时间排序
    bool operator<(const record &a) {
        if (mm == a.mm)
        {
            if (dd == a.dd)
            {
                if (hh == a.hh)
                {
                    return minute < a.minute;
                }
                else return hh < a.hh;
            }
            else return dd < a.dd;
        }
        else return mm < a.mm;
    }

}R[MAXN];

struct Ans {
    int dd_beg, hh_beg, mm_beg,
        dd_end, hh_end, mm_end;
    int amount_time;
    int amount_fee;
    Ans(int _dd_beg, int _hh_beg, int _mm_beg, int _dd_end, int _hh_end, int _mm_end,
        int _amount_time, int _amount_fee)
    {
        dd_beg = _dd_beg, hh_beg = _hh_beg, mm_beg = _mm_beg;
        dd_end = _dd_end, hh_end = _hh_end, mm_end = _mm_end;
        amount_time = _amount_time, amount_fee = _amount_fee;
    }
    bool operator<(const Ans &a)
    {
        if (dd_beg == a.dd_beg)
        {
            if (hh_beg == a.hh_beg)
            {
                return mm_beg < a.mm_beg;
            }
            else return hh_beg < a.hh_beg;
        }
        else return dd_beg < a.dd_beg;
    }
};
// vis 记录离当前 i 最近的名字值为 id 的那条记录的下标
int vis[MAXN];
int fee[30];
map<string, int>hsh;
vector<string>na;
vector<Ans>v[MAXN];
Ans calc(record bg, record ed) {

    if (bg.dd != ed.dd)// 不在同一天内
    {
        int one_day = 0, amount_time = 0;
        int amount_fee = 0;
        for (int i = 0; i < 24; ++i)one_day += fee[i] * 60;
        for (int i = bg.hh + 1; i < 24; ++i)amount_fee += fee[i] * 60, amount_time += 60;

        amount_fee += (60 - bg.minute) * fee[bg.hh]; amount_time += (60 - bg.minute);
        // 算一整天的
        amount_fee += (ed.dd - bg.dd - 1) * one_day; amount_time += 24 * 60 * (ed.dd - bg.dd - 1);

        for (int i = 0; i < ed.hh; ++i)amount_fee += fee[i] * 60, amount_time += 60;
        amount_fee += ed.minute * fee[ed.hh]; amount_time += ed.minute;
        return Ans(bg.dd, bg.hh, bg.minute, ed.dd, ed.hh, ed.minute, amount_time, amount_fee);
    }
    else //同一天内
    {
        int amount_time = 0;
        int amount_fee = 0;
        for (int i = bg.hh + 1; i < ed.hh; ++i)amount_fee += fee[i] * 60, amount_time += 60;
        if (bg.hh == ed.hh) // 同一个小时内
        {
            amount_fee += (ed.minute - bg.minute) * fee[bg.hh];
            amount_time += (ed.minute - bg.minute);
        }
        else
        {
            amount_fee += (60 - bg.minute) * fee[bg.hh]; amount_time += (60 - bg.minute);
            amount_fee += ed.minute * fee[ed.hh]; amount_time += ed.minute;
        }
        return Ans(bg.dd, bg.hh, bg.minute, ed.dd, ed.hh, ed.minute, amount_time, amount_fee);
    }
}

int main() {
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < 24; ++i)scanf("%d", &fee[i]);
    int n, tot = 0; scanf("%d", &n);
    string name, type;
    for (int i = 1; i <= n; ++i)
    {
        cin >> name; scanf("%d:%d:%d:%d", &R[i].mm, &R[i].dd, &R[i].hh, &R[i].minute); cin >> type;
        R[i].name = name; if (hsh.count(name) == 0)
        {
            hsh[name] = ++tot;
            na.push_back(name);
        }
        if (type == "on-line")R[i].type = 0;
        else R[i].type = 1;
    }
    sort(R + 1, R + n + 1);
    sort(na.begin(), na.end());
    for (int i = 1; i <= n; ++i)
    {
        int id = hsh[R[i].name];
        if (R[i].type == 0)
        {
            vis[id] = i;
        }
        else if(vis[id] != 0 && R[i].type == 1)
        {
            v[id].push_back(calc(R[vis[id]], R[i]));
            vis[id] = 0;
        }
    }
    for (int i = 0; i < na.size(); ++i)
    {
        double total = 0;
        int id = hsh[na[i]];
        if (v[id].size() == 0)continue;
        cout << na[i]; printf(" %02d\n", R[1].mm);
        sort(v[id].begin(), v[id].end());
        for (int j = 0; j < v[id].size(); ++j)
        {
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n"
                , v[id][j].dd_beg, v[id][j].hh_beg, v[id][j].mm_beg
                , v[id][j].dd_end, v[id][j].hh_end, v[id][j].mm_end
                , v[id][j].amount_time, v[id][j].amount_fee / 100.0);
            total += v[id][j].amount_fee / 100.0;
        }
        printf("Total amount: $%.2f\n", total);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值