PAT 1016 Phone Bills

这一道题我是按着算法笔记上面来写的。

题目信息比较繁杂,经过思考后我觉得可以分为以下几个步骤来写:

  1. 建立结构体存储record记录。(基础)
  2. 对record的数组按照一定规则进行排序。(基础)
  3. 设置标志分割出同一个用户的所有record。(提高)
  4. 筛选不符合同时拥有上线和下线的记录。(难点)
  5. 在同一个用户所有符合条件的record遍历相邻的record。(提高)
  6. 根据分时段计费准确求出record的费用。(难点)
  7. 计算求出一个用户所有的record费用。(基础)

 

其中有几个难点需要攻克:1.分时段计费如何计算。2.如何有效筛选无用的记录。3.考虑不同用户间记录的过渡。

1.分时段计费

这种方法简洁明了,就是时间复杂度可能比较高。

void getBill(int on,int off,int& time,int& money ){
    record r1 = records[on];
    record r2 = records[off];

    while(r1.day<r2.day||r1.hour<r2.hour||r1.minute<r2.minute){
        time++;
        money += toll[r1.hour];
        r1.minute++;
        if(r1.minute==60){
            r1.minute = 0;
            r1.hour++;
        }
        if(r1.hour==24){
            r1.hour = 0;
            r1.day++;
        }
    }

}

2.筛选无用记录

设置标志,确保每一个用户一定有一对符合条件的记录。

next = on; 
while(next<n&&strcmp(records[next].name,records[on].name)==0){
            if(records[next].status==true&&needprint==0){
                needprint = 1;
            }else if(records[next].status==false&&needprint==1){
                needprint = 2;
            }
            next++;
        }
 if(needprint<2){
            on = next;
            continue;
        }

3.考虑不同用户间记录的过渡

 while(on<next-1 && !(records[on].status==true&&records[on+1].status==false)){
                on++;
            }
            off = on + 1;
            //这里很关键,隐藏了一个测试点
            if(off==next){
                on = next;
                break;
            }

 

代码如下:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

struct record{
    char name[25];
    int month, day, hour, minute;
    bool status;
} records[1010];

bool cmp(record a,record b){
    int flag = strcmp(a.name, b.name);
    if(flag!=0){
        return flag < 0;
    }else if(a.month!=b.month){
        return a.month < b.month;
    }else if(a.day!=b.day){
        return a.day < b.day;
    }else if(a.hour!=b.hour){
        return a.hour < b.hour;
    }else {
        return a.minute < b.minute;
    }
}

int toll[25];
void getBill(int on,int off,int& time,int& money ){
    record r1 = records[on];
    record r2 = records[off];

    while(r1.day<r2.day||r1.hour<r2.hour||r1.minute<r2.minute){
        time++;
        money += toll[r1.hour];
        r1.minute++;
        if(r1.minute==60){
            r1.minute = 0;
            r1.hour++;
        }
        if(r1.hour==24){
            r1.hour = 0;
            r1.day++;
        }
    }

}


int main(){
    for (int i = 0; i < 24;i++){
        scanf("%d", &toll[i]);
    }
    int n;
    scanf("%d", &n);
    char statusline[10];

    for (int i = 0; i < n;i++){
        scanf("%s", records[i].name);
        scanf("%d:%d:%d:%d", &records[i].month,&records[i].day, &records[i].hour, &records[i].minute);
        scanf("%s", statusline);
        if(strcmp(statusline,"on-line")==0){
            records[i].status = true;
        }else{
            records[i].status = false;
        }
    }

    sort(records, records + n, cmp);
    int on = 0, off, next;

    
    while(on<n){
        int needprint = 0;
        next = on;//这里也很关键,不能写成next=on+1,否则会漏了第一组数据

        while(next<n&&strcmp(records[next].name,records[on].name)==0){
            if(records[next].status==true&&needprint==0){
                needprint = 1;
            }else if(records[next].status==false&&needprint==1){
                needprint = 2;
            }
            next++;
        }

        if(needprint<2){
            on = next;
            continue;
        }

        int allmoney = 0;
        printf("%s %02d\n", records[on].name, records[on].month);

        while(on<next){
            while(on<next-1 && !(records[on].status==true&&records[on+1].status==false)){
                on++;
            }
            off = on + 1;
            //这里很关键,隐藏了一个测试点
            if(off==next){
                on = next;
                break;
            }

            printf("%02d:%02d:%02d ", records[on].day, records[on].hour, records[on].minute);
            printf("%02d:%02d:%02d ", records[off].day, records[off].hour, records[off].minute);

            int money = 0, time = 0;
            getBill(on, off, time, money);
            allmoney += money;
            printf("%d $%.2f\n", time, money / 100.0);

            on = off + 1;

        }

        printf("Total amount: $%.2f\n",allmoney/100.0);
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值