PAT-1016 Phone Bills (25)

http://pat.zju.edu.cn/contests/pat-a-practise/1016

#include<stdio.h> #include<algorithm> #include<string> #include<vector> #include<iostream> using namespace std; struct Time { int dd; int hh; int mm; }; struct Record { string name; int mon; int dd; int hh; int mm; bool flag;//true on,false for of }record[1010]; struct Bill { Time begin; Time end; }bill[1010][13];// name index and month int cost[24]; double compute(Time b,Time e) { int j=b.hh; int d=b.dd; double sum=0; if(b.dd==e.dd&&b.hh==e.hh) { return (e.mm-b.mm)*cost[j]; } sum+=(60-b.mm)*cost[j]; while(true) { //printf("%d %d %lf ",d,j,sum); j++; if(j>=24) { j=j%24; d++; } if(d==e.dd&&j>=e.hh) break; sum+=cost[j]*60; } sum+=e.mm*cost[j]; //printf("%d %d %lf ",d,j,sum); //printf(" "); return sum; } bool cmp(const Record & a,const Record & b) { if(a.name<b.name) return true; else if(a.name==b.name) { if(a.mon<b.mon) return true; else if(a.mon==b.mon) { if(a.dd<b.dd) return true; else if(a.dd==b.dd) { if(a.hh<b.hh) return true; else if(a.hh==b.hh) { if(a.mm<b.mm) return true; } } } } return false; } void parse(string str,int &mon,int &dd,int &hh,int &mm) { int a=0,b=0; for(int i=0;i<str.length();i=i+3) { a=str[i]-'0'; b=str[i+1]-'0'; int temp=a*10+b; switch(i/3+1) { case 1: mon=temp; break; case 2: dd=temp; break; case 3: hh=temp; break; case 4: mm=temp; break; } } } int main() { freopen("1016-in.txt","r",stdin); freopen("1016-out.txt","w",stdout); vector<string> name_set; for(int i=0;i<24;i++) { scanf("%d",&cost[i]); } int n; string name,time,flag; int mon,dd,hh,mm; vector<string>::iterator it; scanf("%d",&n); for(int i=0;i<n;i++) { cin>>name>>time>>flag; name_set.push_back(name); //it=find(name_set.begin(),name_set.end(),name); //cout<<name<<time<<flag; parse(time,mon,dd,hh,mm); //cout<<mon<<dd<<hh<<mm<<endl; record[i].name=name; record[i].mon=mon; record[i].dd=dd; record[i].hh=hh; record[i].mm=mm; if(flag=="on-line") { record[i].flag=true; } else { record[i].flag=false; } } sort(record,record+n,cmp);

string pre=record[0].name; int count=name_set.size(); string pre_name=""; int pre_month=-1; int sum_min=0; double sum_cost=0; bool is_print=false; for(int i=0;i<n;i++) { if(record[i].flag&&!record[i+1].flag&&record[i].name==record[i+1].name&&record[i].mon==record[i+1].mon) { it=find(name_set.begin(),name_set.end(),record[i].name); int index=name_set.begin()-it; int mon=record[i].mon; int lapse=(record[i+1].dd-record[i].dd)*24*60+(record[i+1].hh-record[i].hh)*60+(record[i+1].mm-record[i].mm); string name=record[i].name; if(name!=pre_name||mon!=pre_month) printf("%s %02d ",name.c_str(),mon); Time b,e; b.dd=record[i].dd; b.hh=record[i].hh; b.mm=record[i].mm; e.dd=record[i+1].dd; e.hh=record[i+1].hh; e.mm=record[i+1].mm; sum_cost+=compute(b,e); printf("%02d:%02d:%02d %02d:%02d:%02d %d $%0.2lf ",record[i].dd,record[i].hh,record[i].mm,record[i+1].dd,record[i+1].hh,record[i+1].mm,lapse,compute(b,e)/100.0); is_print=true; i++; pre_name=name; pre_month=mon; } if(record[i].name!=record[i+1].name&&is_print)//打印输出文件时候,用户存在一个匹配输入都没有的情况,那么什么都不输出。 { printf("Total amount: $%0.2lf ",sum_cost/100.0); sum_cost=0; is_print=false; } } // 数据结构的设计应该和输出保持一致性,这样才能更好地输出 return 0; }

PAT:

     这道题目的意思就是,给你一个电话账单。然后计算用户的的话费,这道题目坐下来比较大的一个启发就是,当你考虑的情况很多的时候,你可以考虑一下反面,这样就会简单多了。比如错误的情况很多,那么久考虑正确的情况。正确情况很多,那么就考虑错误的情况,比如账单中错误的顺序很多比如off on,不是同一个月份,不是同一个而用户等等。通过if(record[i].flag&&!record[i+1].flag&&record[i].name==record[i+1].name&&record[i].mon==record[i+1].mon)来进行判就可以了。其余错误情况就不去管它了。

   时间金钱的计算有一个难点,起初就是把开头和结尾的截掉,只是取中间整数部分,开头结尾另外算。不过当时没有考虑一个case,就是相差仅仅一个小时之内的情况,这种情况比如01:01:02:23 -- 01:01:02:25这种情况要是用起初的情况,那么计算出来就是60-23分钟,显然不对,所以在计算的时候加入了一个特别判断。

    bool cmp(first,second)的返回值意思是first should before second?return true ,yes。return false,no

    这道题目太繁杂了,起初只有过了一个case,后面网上一下,发现用户可能没有合法的输入,只保证每次输入有一个合法的输入。增加一个flag之后过了一个case

chun 01:01:23:59 on-line
chun 01:02:00:59 off-line

比如这样的临街测试数据,发现这道题目临界数据挺多的。还是得多测试临界数据,考察临界情况。

原文地址:https://www.cnblogs.com/championlai/p/3986851.html