1. 程式人生 > >pat 甲級測試題目 -- 1016 Phone Bills

pat 甲級測試題目 -- 1016 Phone Bills

vector pin 希望 定義 思路 代碼 計算 學習 描述

題目鏈接

題目描述

要求計算銀行賬單。
輸入
第一行給你一天24小時(00:00~01:00 ...)每個小時每分鐘的話費,單位是美分
第二行給你顧客列表(N 個)
接下來的 N 行是顧客的賬單詳情
CYLL 01:01:06:01 on-line
姓名 月:日:小時:分鐘 狀態
CYLL 01:28:16:05 off-line
姓名 月:日:小時:分鐘 狀態
on-line 和 off-line 必須一一對應該記錄才有效

輸出
對於輸入有效的顧客,給出該顧客這個月的賬單,格式如下
CYJJ 01
姓名 月份
01:05:59 01:07:00 61 $12.10
通話開始時間 通話結束時間 話費
Total amount: $12.10

這個月的總額話費

註意:
每次的輸入,顧客的月份都是一樣的。
測試用例中會出現跨天的情況。

分析

看到這道題目之後,我考慮過單純的使用 map 或者結構體存儲數據,最後確定用 map<string, vector>,也就是map + vector + 結構體 的方式存儲。盡管成功的存儲了,但是到了處理數據這裏,對於姓名排序以及時間排序的處理讓我著實頭痛。無奈就去參考了網上的代碼。參考網址
不得不說柳神真的是名不虛傳。不僅用總計日時分的時間解決了時間上的排序問題,而且用總計日時分的話費解決了跨天的話費計算問題,這兩個方法都有共性吧。。。學習到了!我參考(抄襲←_←)柳神的代碼後,將其思路列在代碼註釋裏面了

實現

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <string>

using namespace std;

struct node {
    string name;
    int month, day, hour, minute, statue, time; // 定義 time 用於比較時間
};

bool cmp(node a, node b) {
    return a.name == b.name ? a.time < b.time : a.name < b.name; // 按照姓名比較,姓名相同按照時間比較,方便計算費用
}
// 計算總時間的話費,用於解決跨天問題
double CallSpend(node cus, int* rate){
    double total = rate[cus.hour] * cus.minute + cus.day * rate[24] * 60;
    for (int i = 0; i < cus.hour; ++i) {
        total += rate[i] * 60;
    }
    return total/100;
}


int main() {
    int rate[25] = {0}, n;
    // 接收計費數據
    for (int i = 0; i < 24; ++i) {
        cin >> rate[i];
        rate[24] += rate[i]; // 將一天的話費數據計算出來,用於解決跨天計算話費的問題
    }
    cin >> n;
    vector<node> custom(n);
    for (int i = 0; i < n; ++i) {
        cin >> custom[i].name;
        scanf("%d:%d:%d:%d", &custom[i].month, &custom[i].day, &custom[i].hour, &custom[i].minute);
        string stemp;
        cin >> stemp;
        custom[i].statue = ((stemp == "on-line") ? 1 : 0);
        custom[i].time = custom[i].day * 24 * 60 + custom[i].hour * 60 + custom[i].minute;
    }
    // 對顧客數據進行排序
    sort(custom.begin(), custom.end(), cmp);
    // 用 map 存儲數據,將同一個顧客的月賬單統一
    map<string, vector<node>> list;
    for (int i = 1; i < n; ++i) {
        if (custom[i].name == custom[i - 1].name && custom[i - 1].statue == 1 && custom[i].statue == 0) {
            list[custom[i - 1].name].push_back(custom[i - 1]);
            list[custom[i].name].push_back(custom[i]);
        }
    }
    // 遍歷 map 輸出賬單
    for (auto li : list) {
        vector<node> temp = li.second;
        cout << li.first;
        printf(" %02d\n", temp.front().month);
        double total = 0;
        for (int i = 1; i < temp.size(); i+=2) {
            // 計算一次通話記錄的話費
            double t = CallSpend(temp[i], rate) - CallSpend(temp[i-1], rate);
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", temp[i-1].day, temp[i-1].hour, temp[i-1].minute, temp[i].day, temp[i].hour, temp[i].minute, temp[i].time - temp[i-1].time, t);
            total += t;
        }
        printf("Total amount: $%.2f\n", total);
    }
    return 0;
}

希望能幫到大家

pat 甲級測試題目 -- 1016 Phone Bills