日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!)

發布時間:2025/4/5 c/c++ 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 題目分析
    • 題目鏈接

題目分析

原題:

長途電話公司按以下規則向客戶收費:

撥打長途電話每分鐘要花費一定的費用,具體收費取決于撥打電話的時間。

客戶開始撥打長途電話的時間將被記錄,客戶掛斷電話的時間也將被記錄。

每個月都要給客戶發送一次話費賬單,賬單中應包含每次通話記錄以及相關收費等信息。

給定一組電話記錄,你的工作是為客戶準備帳單。

輸入格式
輸入包含兩部分:費率結構和電話記錄。

費率結構由一行組成,該行包含24個非負整數,分別表示從 00:00-01:00 的收費(分/分鐘),從 01:00-02:00 的收費,以此類推…

下一行包含一個正整數 N。

接下來 N 行,每行包含一條記錄。

每個記錄由客戶名稱(最多 20 個字符的字符串,不帶空格),時間和日期(mm:dd:hh:mm)以及單詞 on-line 或 off-line 組成。

所有日期都在同一個月內,每個 on-line 記錄都與按時間順序排列的同一位客戶的下一條記錄配對,但前提是這條記錄是 off-line。

所有未與 off-line 記錄配對的 on-line 記錄以及未與 on-line 記錄配對的 off-line 記錄都必須忽略。

輸入中至少包含一個成功的配對。

同一客戶在同一時間不會有兩個或以上的電話記錄。

使用 24 小時制記錄時間。

輸出格式
你需要為每個客戶打印電話費。

賬單必須按照客戶姓名的字母順序(按ASCII碼順序,大寫字母在前,小寫字母在后)打印。

對于每個客戶,首先以示例顯示的格式在一行中打印客戶名稱和帳單月份。

然后,對于每個通話時間段,在一行中分別打印開始和結束時間和日期(dd:hh:mm),持續時間(以分鐘為單位)和通話費用。

通話必須按時間順序列出。

最后,以示例顯示的格式打印該月的總費用。

注意,沒有任何有效通話記錄的客戶直接忽略,不予打印賬單。

數據范圍
1≤N≤1000

題目分析:

特點:題干很長,需要花時間去閱讀。

分析:這道題有點不會處理,在糾結用不用結構體。

  • 很多信息使用結構體,然后使用map建立映射,本題map< 姓名, vector<結構體> > 。 這樣保存聯系,當然需要熟悉結構體排序sort,重載< 或者重寫cmp函數。
  • 后面字符串中 CYLL 01:01:06:01 on-line 月份、日期、小時、分鐘用int數來存,不用字符串來存。
  • 復雜讀入、輸出多用C語言!!!!
  • 另外需要提到的一點是:讀入數據是沒有順序的,可能off-line的在前,也可能on-line的在前。但是好在 同一個人打電話區域是不重疊的!!!什么意思呢?意思是 張三1月1號7:00開始打電話,打到1月1號7:15,這是一次完整的通話,數據中不會出現張三1月1號7:10又開始打電話(上一次數據是7:00 ~ 7:15,7:10開始打電話與之沖突)這種數據。

    想到了這一點,就可以僅僅按照時間來排序,而不用在排序的時候還要考慮online還是offline。 因為 按時間排好之后一次完整的通話一定是在一起的,即上面的是online,下一個就是同一次通話的offline。沒有在一起的就是非法數據。

    學習很多C語言的優點

    sprintf函數的作用:將一個格式化的字符串輸入到另一個字符串中。sprintf()一般是三個參數:第一個是目的字符串,第二個是格式,比如“%02d”,第三個就是變量。

    比如

    char buf[30]; int day ,hour ,minute; //假設已經賦過值 sprintf(buf , "%02d:%02d:%02d", day , hour , minute); //意思是格式化為xx:xx:xx 這樣的形式 xx不足兩位的補零

    sprintf()函數的用法總結

    還有 .c_str()函數,

    使用printf("%s")輸出的時候需要 char * ,不能使用string類型, 需要函數 c_str()進行轉換:把string轉換為 char *

    warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::string' {aka 'std::basic_string<char>'} [-Wformat=]

    ac代碼

    學習別人的代碼

    #include<bits/stdc++.h> using namespace std;const int N =1010,M=31*1440+10; // 每天1440分鐘,每月最多31天。另外再多開10個大小 int cost[24];struct Record{int minutes; //字符串時間轉化為分鐘數string state;string format_time;//按照時間從小到大排序, 重載 < 運算符bool operator< (const Record& t)const{return minutes < t.minutes;} };//hash表映射 // 第一個是name ,后面是一個vector ,vector里面存了一個結構體。 //同名字的記錄都push_back到 vector中作為一項。/* 差不多是這樣的 張三對應一個vector: {一條記錄(結構體),一條記錄,一條記錄,...} 李四對應一個vector:{一條記錄(結構體),一條記錄,一條記錄,...} */ map<string,vector<Record>> persons;double sum[M];// 前綴和數組,用來求本月1號0點0分 到任何一天任何時間花費的錢數int n;int main(){for(int i=0;i<24;i++) cin >>cost[i];// 預處理 本月1號00:00分 到 本月 任意時間x號xx:xx分 打電話的花費//i 這里遍歷的是一個月中的所有分鐘 // %1440 是看在幾號(一天1440分鐘) ;而/60是看在哪個小時時間段,用來看此時的電話費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號00時00分的分鐘數,方便前綴和求解persons[name].push_back({minutes, state, format_time}); //結構體壓入姓名對應的vector} for( const auto & p :persons ){auto name = p.first;auto records = p.second; //是map里面的那個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代碼:
    自己獨立寫的代碼:vector自定義排序還是喜歡重寫cmp函數,這里比較的是結構體。

    #include<bits/stdc++.h> using namespace std;const int N =1000 , M =24*60; //M一天多少分鐘const int minutesOfAMonth= 31*M+10;struct Record{int minute; //存這個時間到初始之差string formatTime; //格式化的信息string state; //狀態 offline還是online};//結構體按照 時間排序 //因為vector里面存的是結構體,所以要對結構體進行操作。 bool cmp(Record a, Record b){return a.minute < b.minute; }//姓名 和自己的記錄 之間的map map<string ,vector<Record>> records;int cost[30];//剛開始,sum前綴和類型寫成int了,不要犯這種小錯誤。 double sum[minutesOfAMonth];int main(){int n;for(int i=0;i<24;i++) cin>>cost[i];for(int i=1;i<minutesOfAMonth;i++) sum[i] = sum[i-1] + cost[ (i-1) %M / 60 ]/100.0;cin>>n;char name[25] ,state[10],formatTime[20];int month ,day ,hour, minute;//信息全部讀入在records中for(int i=0;i<n;i ++){scanf("%s %02d:%02d:%02d:%02d %s", name ,&month ,&day ,&hour, &minute, state);int minutes = (day-1)*M + hour*60 + minute;sprintf(formatTime,"%02d:%02d:%02d",day, hour ,minute );//cout<<formatTime <<endl;records[name].push_back({minutes,formatTime ,state });}//處理records中的數據for(const auto & rec : records){double total =0;auto name = rec.first;auto person = rec.second;// person 是個vectorsort(person.begin(),person.end(),cmp);//每次遍歷2個記錄for( unsigned i =0;i+1 <person.size(); i++){ auto a = person[i], b = person[i+1];if(a.state=="on-line" && b.state== "off-line"){//每個人只輸出一次姓名和月份,如果total==0 ,代表剛開始這個人,所以輸出if(!total){printf("%s %02d\n", name.c_str() , month); // C語言中string轉化成char * 類:函數c_str() }double charge = sum[b.minute] - sum[a.minute];printf("%s %s %d $%.2lf\n", a.formatTime.c_str(), b.formatTime.c_str(), b.minute - a.minute, charge );total += charge;}}//如果total不為0,代表這個人合法,則需要輸出總費用if(total) printf("Total amount: $%.2lf\n",total);}}

    題目鏈接

    PAT甲級1016 Phone Bills

    總結

    以上是生活随笔為你收集整理的PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。