PAT(Phone Bills)

参考:https://blog.csdn.net/xyt8023y/article/details/46010349


1. 题目有点奇葩:
  • 时间是打乱顺序给你的,而且不一定是有效数据(一个on对应一个off),需要从低到高排序,然后把无效数据过滤掉,如果过滤后没有on-off对的话就不打印。
  • 给了24个小时的cents/每分钟的开销。一百cents兑换一美元。

为了解决on和off存储的问题,我选择使用正负号来区分on和off。


分以下四种情况:
i指向on,j指向off
++    i++  j++
--    i=j+1 j+=2
+-    i=j+1 j+=2
-+    i++  j++

我的流程:

将输入写入vector后按照字母次序排序:

// 打印的时候要按照字符大小排序(ascii码小的放前面)
bool cmpstr(customer&left,customer&right){
  // 逐个字符比较,从小到大排序,防止前面一串出现重复
  int leftlen=strlen(left.name);
  int rightlen=strlen(right.name);
  int length=min(leftlen,rightlen);
  int i,j;
  for(i=0;i<length;i++){
    if(left.name[i]==right.name[i]){

    }
    else{
      return left.name[i]<right.name[i];
    }
  }
  return leftlen<rightlen;
}

数据清理:

对每一个人的time进行排序:

  // 按照题目要求的字符串方式排序
  sort(v.begin(),v.end(),cmpstr);
  for(i=0;i<v.size();i++){
    // 对时间从小到大排序
    sort(v[i].time.begin(),v[i].time.end(),cmptime);
  }

打印每个人的数据:

边过滤边将合法的on-off插入vector中(记得取绝对值):

void print(vector<customer>&v,int num){
  int i=0,j=1;
  float sum=0;
  // 计算总价
  vector<int>record;
  while(j<v[num].time.size()){
    if(v[num].time[i]>0&&v[num].time[j]<0){
      int start=v[num].time[i];
      int ending=v[num].time[j];
      record.push_back(start);
      record.push_back(ending);
    }
    if(v[num].time[j]>0){
      i++;
      j++;
    }
    else if(v[num].time[j]<0){
      i=j+1;
      j+=2;
    }
  }
  if(record.empty()){
    return;
  }
  printf("%s %02d\n",v[num].name,monthnow);
  for(i=0;i<record.size();i+=2){
    PrintTime(record[i]);
    PrintTime(abs(record[i+1]));
    int time=-(record[i]+record[i+1]);
    cout<<time<<" ";
    sum+=sumup(record[i],abs(record[i+1]));
  }
  printf("Total amount: $%.2f\n",sum);
}

根据开始结束时间计算收费

float sumup(int start,int ending){
  int i,j;
  int start_hours=start/60;
  int start_minutes=start%60;
  int ending_hours=ending/60;
  int ending_minutes=ending%60;
  float cost=0;
  for(i=start_hours+1;i<ending_hours;i++){
    cost+=60*costs[i%24];
  }
  cost+=costs[ending_hours%24]*(ending_minutes);
  cost+=costs[start_hours%24]*(60-start_minutes);
  cost/=100;
  printf("$%.2f\n",cost);
  return cost;
}

以上模块有两个问题,一个在计算中不提前除以100.00的话有可能会溢出。一个是算法错了,在同一个小时内的call会出现计算错误,下面这个算法计算了start到0:0:0的开销如何减去ending到0:0:0的开销得出了正确的结论。

double caculate(int t)
{
    int i,j;
    double sum=0;
    for(i=0;i<t/60;i++)
    {
        sum+=costs[i%24]*60/100.0;
    }
    sum+=costs[i%24]*(t%60)/100.0;
    return sum;
}
double sumup(int start,int ending)
{
    double cost=caculate(ending)-caculate(start);
    printf("$%.2lf\n",cost);
    return cost;
}

我的代码:

#include<bits/stdc++.h>
using namespace std;
typedef struct customer{
  vector<int>time;
  // +on -off
  string name;
  int namehash;
}customer;
map<string,customer>m;

int costs[24]={0};
int monthnow=0;
// 月份是固定的,单独存放
vector<customer>v;

// 查找hash值是否存在,不存在就返回-1
int searchmap(char name[]){
  int i,j;
  if(m.count(name)==1){
    return 1;
  }
  return -1;
}
// 根据名字hash从小到大排列,方便二叉查找
bool cmp(customer&left,customer&right){
  return left.namehash<right.namehash;
}
// 打印的时候要按照字符大小排序(ascii码小的放前面)
bool cmpstr(customer&left,customer&right){
  // 逐个字符比较,从小到大排序,防止前面一串出现重复
  int leftlen=left.name.size();
  int rightlen=right.name.size();
  int length=min(leftlen,rightlen);
  int i,j;
  for(i=0;i<length;i++){
    if(left.name[i]==right.name[i]){

    }
    else{
      return left.name[i]<right.name[i];
    }
  }
  return leftlen<rightlen;
}
bool cmptime(int a,int b){
  return abs(a)<abs(b);
}
void PrintTime(int time){
  printf("%02d:%02d:%02d ",time/(60*24),(time%(60*24))/60,(time%(60*24))%60);
}
double caculate(int t)
{
    int i,j;
    double sum=0;
    for(i=0;i<t/60;i++)
    {
        sum+=costs[i%24]*60/100.0;
    }
    sum+=costs[i%24]*(t%60)/100.0;
    return sum;
}
double sumup(int start,int ending)
{
    double cost=caculate(ending)-caculate(start);
    printf("$%.2lf\n",cost);
    return cost;
}
void print(vector<customer>&v,int num){
  int i=0,j=1;
  double sum=0;
  // 计算总价
  vector<int>record;
  while(j<v[num].time.size()){
    if(v[num].time[i]>0&&v[num].time[j]<0){
      int start=v[num].time[i];
      int ending=v[num].time[j];
      record.push_back(start);
      record.push_back(ending);
    }
    if(v[num].time[j]>0){
      i++;
      j++;
    }
    else if(v[num].time[j]<0){
      i=j+1;
      j+=2;
    }
  }
  if(record.empty()){
    return;
  }
  printf("%s %02d\n",v[num].name.c_str(),monthnow);
  for(i=0;i<record.size();i+=2){
    PrintTime(record[i]);
    PrintTime(abs(record[i+1]));
    int time=-(record[i]+record[i+1]);
    cout<<time<<" ";
    sum+=sumup(record[i],abs(record[i+1]));
  }
  printf("Total amount: $%.2f\n",sum);
}
int main(){
  int i,j,input;
  for(i=0;i<24;i++){
    scanf("%d",&input);
    costs[i]=input;
  }
  scanf("%d",&input);

  char name[50],sign[20];
  int month,day,hour,minutes,namehash;
  for(j=0;j<input;j++){
    scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minutes,sign);
    monthnow=month;
    // cout<<"))))))))"<<endl;
    if(!strcmp(sign,"off-line")){
      // 匹配offline成功则返回0
      int target=searchmap(name);
      if(target==-1){
        // 没找到
        customer c;
        c.name=name;
        //c.namehash=hashname(name);
        c.time.push_back((minutes+60*hour+24*60*day)*-1);
        m[name]=c;
        //v.push_back(c);
        // sort(v.begin(),v.end(),cmpstr);
      }
      else{
        m[name].time.push_back((minutes+60*hour+24*60*day)*-1);
        // v[target].time.push_back((minutes+60*hour+24*60*day)*-1);
      }
    }
    else{
      int target=searchmap(name);
      if(target==-1){
        // 没找到
        customer c;
        c.name=name;
        c.time.push_back(minutes+60*hour+24*60*day);
        m[name]=c;
      }
      else{
        m[name].time.push_back(minutes+60*hour+24*60*day);
      }
    }
  }
  for(map<string,customer>::iterator it=m.begin();it!=m.end();it++){
    v.push_back(it->second);
  }
  // 按照题目要求的字符串方式排序
  sort(v.begin(),v.end(),cmpstr);
  for(i=0;i<v.size();i++){
    // 对时间从小到大排序
    sort(v[i].time.begin(),v[i].time.end(),cmptime);
  }
  // 筛选每个customers的bills然后打印
  for(i=0;i<v.size();i++){
    print(v,i);
  }
}

测试数据:


测试用例:
72 53 94 95 71 82 31 1 97 36 8 94 44 22 3 51 58 72 27 57 7 39 55 80 38 
CS07 07:11:04:05 off-line 
CS05 07:15:19:37 on-line 
CS09 07:26:10:05 on-line 
CS00 07:29:08:20 off-line 
CS00 07:27:16:05 on-line 
CS06 07:25:13:50 off-line 
CS07 07:17:08:03 on-line 
CS04 07:25:02:50 on-line 
CS02 07:05:09:47 on-line 
CS03 07:23:18:20 on-line 
CS05 07:30:05:51 on-line 
CS06 07:08:11:57 off-line 
CS05 07:13:18:12 on-line 
CS07 07:21:07:52 off-line 
CS08 07:14:12:34 off-line 
CS04 07:21:18:49 off-line 
CS00 07:31:11:35 on-line 
CS09 07:03:10:58 on-line 
CS08 07:17:01:46 off-line 
CS06 07:02:02:30 off-line 
CS07 07:16:08:51 on-line 
CS02 07:29:17:32 off-line 
CS03 07:14:19:43 on-line 
CS05 07:12:06:43 off-line 
CS09 07:25:04:45 off-line 
CS04 07:23:15:19 on-line 
CS08 07:03:10:42 on-line 
CS03 07:01:12:02 off-line 
CS07 07:30:07:23 off-line 
CS03 07:28:14:33 off-line 
CS00 07:08:18:33 off-line 
CS08 07:13:13:44 off-line 
CS02 07:30:13:47 on-line 
CS06 07:14:21:54 on-line 
CS00 07:09:21:00 on-line 
CS02 07:24:12:24 off-line 
CS09 07:24:19:24 off-line 
CS03 07:16:02:33 on-line 
对应输出应该为:
CS00 07 27:16:05 29:08:20 2415 $1302.30 Total amount: $1302.30 
CS02 07 05:09:47 24:12:24 27517 $14315.04 Total amount: $14315.04 
CS03 07 23:18:20 28:14:33 6973 $3632.19 Total amount: $3632.19 
CS06 07 14:21:54 25:13:50 15356 $8055.14 Total amount: $8055.14 
CS07 07 17:08:03 21:07:52 5749 $2994.61 Total amount: $2994.61 
CS08 07 03:10:42 13:13:44 14582 $7587.92 Total amount: $7587.92 
CS09 07 03:10:58 24:19:24 30746 $15973.84 Total amount: $15973.84 
你的输出为:
CS00 07 27:16:05 29:08:20 2415 $1302.30 Total amount: $1302.30 
CS02 07 05:09:47 24:12:24 27517 $14315.05
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容