PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!)
文章目錄
- 題目分析
- 題目鏈接
題目分析
原題:
長途電話公司按以下規(guī)則向客戶收費(fèi):
撥打長途電話每分鐘要花費(fèi)一定的費(fèi)用,具體收費(fèi)取決于撥打電話的時(shí)間。
客戶開始撥打長途電話的時(shí)間將被記錄,客戶掛斷電話的時(shí)間也將被記錄。
每個(gè)月都要給客戶發(fā)送一次話費(fèi)賬單,賬單中應(yīng)包含每次通話記錄以及相關(guān)收費(fèi)等信息。
給定一組電話記錄,你的工作是為客戶準(zhǔn)備帳單。
輸入格式
輸入包含兩部分:費(fèi)率結(jié)構(gòu)和電話記錄。
費(fèi)率結(jié)構(gòu)由一行組成,該行包含24個(gè)非負(fù)整數(shù),分別表示從 00:00-01:00 的收費(fèi)(分/分鐘),從 01:00-02:00 的收費(fèi),以此類推…
下一行包含一個(gè)正整數(shù) N。
接下來 N 行,每行包含一條記錄。
每個(gè)記錄由客戶名稱(最多 20 個(gè)字符的字符串,不帶空格),時(shí)間和日期(mm:dd:hh:mm)以及單詞 on-line 或 off-line 組成。
所有日期都在同一個(gè)月內(nèi),每個(gè) on-line 記錄都與按時(shí)間順序排列的同一位客戶的下一條記錄配對(duì),但前提是這條記錄是 off-line。
所有未與 off-line 記錄配對(duì)的 on-line 記錄以及未與 on-line 記錄配對(duì)的 off-line 記錄都必須忽略。
輸入中至少包含一個(gè)成功的配對(duì)。
同一客戶在同一時(shí)間不會(huì)有兩個(gè)或以上的電話記錄。
使用 24 小時(shí)制記錄時(shí)間。
輸出格式
你需要為每個(gè)客戶打印電話費(fèi)。
賬單必須按照客戶姓名的字母順序(按ASCII碼順序,大寫字母在前,小寫字母在后)打印。
對(duì)于每個(gè)客戶,首先以示例顯示的格式在一行中打印客戶名稱和帳單月份。
然后,對(duì)于每個(gè)通話時(shí)間段,在一行中分別打印開始和結(jié)束時(shí)間和日期(dd:hh:mm),持續(xù)時(shí)間(以分鐘為單位)和通話費(fèi)用。
通話必須按時(shí)間順序列出。
最后,以示例顯示的格式打印該月的總費(fèi)用。
注意,沒有任何有效通話記錄的客戶直接忽略,不予打印賬單。
數(shù)據(jù)范圍
1≤N≤1000
題目分析:
特點(diǎn):題干很長,需要花時(shí)間去閱讀。
分析:這道題有點(diǎn)不會(huì)處理,在糾結(jié)用不用結(jié)構(gòu)體。
另外需要提到的一點(diǎn)是:讀入數(shù)據(jù)是沒有順序的,可能off-line的在前,也可能on-line的在前。但是好在 同一個(gè)人打電話區(qū)域是不重疊的!!!什么意思呢?意思是 張三1月1號(hào)7:00開始打電話,打到1月1號(hào)7:15,這是一次完整的通話,數(shù)據(jù)中不會(huì)出現(xiàn)張三1月1號(hào)7:10又開始打電話(上一次數(shù)據(jù)是7:00 ~ 7:15,7:10開始打電話與之沖突)這種數(shù)據(jù)。
想到了這一點(diǎn),就可以僅僅按照時(shí)間來排序,而不用在排序的時(shí)候還要考慮online還是offline。 因?yàn)?按時(shí)間排好之后一次完整的通話一定是在一起的,即上面的是online,下一個(gè)就是同一次通話的offline。沒有在一起的就是非法數(shù)據(jù)。
學(xué)習(xí)很多C語言的優(yōu)點(diǎn)
sprintf函數(shù)的作用:將一個(gè)格式化的字符串輸入到另一個(gè)字符串中。sprintf()一般是三個(gè)參數(shù):第一個(gè)是目的字符串,第二個(gè)是格式,比如“%02d”,第三個(gè)就是變量。
比如
char buf[30]; int day ,hour ,minute; //假設(shè)已經(jīng)賦過值 sprintf(buf , "%02d:%02d:%02d", day , hour , minute); //意思是格式化為xx:xx:xx 這樣的形式 xx不足兩位的補(bǔ)零sprintf()函數(shù)的用法總結(jié)
還有 .c_str()函數(shù),
使用printf("%s")輸出的時(shí)候需要 char * ,不能使用string類型, 需要函數(shù) c_str()進(jìn)行轉(zhuǎn)換:把string轉(zhuǎn)換為 char *
warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::string' {aka 'std::basic_string<char>'} [-Wformat=]ac代碼
學(xué)習(xí)別人的代碼
#include<bits/stdc++.h> using namespace std;const int N =1010,M=31*1440+10; // 每天1440分鐘,每月最多31天。另外再多開10個(gè)大小 int cost[24];struct Record{int minutes; //字符串時(shí)間轉(zhuǎn)化為分鐘數(shù)string state;string format_time;//按照時(shí)間從小到大排序, 重載 < 運(yùn)算符bool operator< (const Record& t)const{return minutes < t.minutes;} };//hash表映射 // 第一個(gè)是name ,后面是一個(gè)vector ,vector里面存了一個(gè)結(jié)構(gòu)體。 //同名字的記錄都push_back到 vector中作為一項(xiàng)。/* 差不多是這樣的 張三對(duì)應(yīng)一個(gè)vector: {一條記錄(結(jié)構(gòu)體),一條記錄,一條記錄,...} 李四對(duì)應(yīng)一個(gè)vector:{一條記錄(結(jié)構(gòu)體),一條記錄,一條記錄,...} */ map<string,vector<Record>> persons;double sum[M];// 前綴和數(shù)組,用來求本月1號(hào)0點(diǎn)0分 到任何一天任何時(shí)間花費(fèi)的錢數(shù)int n;int main(){for(int i=0;i<24;i++) cin >>cost[i];// 預(yù)處理 本月1號(hào)00:00分 到 本月 任意時(shí)間x號(hào)xx:xx分 打電話的花費(fèi)//i 這里遍歷的是一個(gè)月中的所有分鐘 // %1440 是看在幾號(hào)(一天1440分鐘) ;而/60是看在哪個(gè)小時(shí)時(shí)間段,用來看此時(shí)的電話費(fèi)for(int i=0; i< M ;i++) sum[i] =sum[i-1] + cost[ (i- 1) % 1440 / 60 ] /100.0;cin>>n;char name[25] ,state[10], format_time[20];int month ,day ,hour ,minute;for(int i=0;i<n;i++){scanf("%s %d:%d:%d:%d %s",name, &month, &day, &hour, &minute, state);sprintf(format_time ,"%02d:%02d:%02d", day ,hour ,minute);int minutes = (day -1) * 1440 +hour * 60 + minute; //記錄距離該月1號(hào)00時(shí)00分的分鐘數(shù),方便前綴和求解persons[name].push_back({minutes, state, format_time}); //結(jié)構(gòu)體壓入姓名對(duì)應(yīng)的vector} for( const auto & p :persons ){auto name = p.first;auto records = p.second; //是map里面的那個(gè)vectorsort(records.begin(),records.end());double total = 0;for(long unsigned i=0 ; i + 1 < records.size() ;i ++){ //每次遍歷兩條記錄auto a = records[i] ,b = records[i+1];if(a.state == "on-line" && b.state =="off-line"){if(!total){printf("%s %02d\n",name.c_str(),month); // 輸出姓名和月份}cout<< a.format_time <<" "<<b.format_time<<" ";double charge = sum[b.minutes] -sum[a.minutes];printf("%d $%.2lf\n",b.minutes - a.minutes, charge);total+=charge;}}if(total) printf("Total amount: $%.2lf\n",total);}}ac代碼:
自己獨(dú)立寫的代碼:vector自定義排序還是喜歡重寫cmp函數(shù),這里比較的是結(jié)構(gòu)體。
題目鏈接
PAT甲級(jí)1016 Phone Bills
總結(jié)
以上是生活随笔為你收集整理的PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PAT甲级1061 Dating:[C+
- 下一篇: PAT甲级1017 Queueing a