Algorithm 06 - patA1016 telephone bill problem (pairing sorting and summation)

Posted by robvan75 on Mon, 24 Jan 2022 21:41:14 +0100

Title Description:
   give the charge (cents/minute) of each hour interval in 24h, and give N call recording points. Each call recording point records the name, current time (month: Day: hour: minute) and whether it belongs to on-line or off-line. Now it is necessary to calculate the tariff of each person's effective call records. Effective call records refer to all on-line and off-line that the same user can pair, and such pairing needs to meet: after being arranged in chronological order, other on-line and off-line records are not allowed in the time corresponding to the two paired on-line and off-line.

Output requirements:
   output users with valid call records from small to large according to the dictionary order of names. For a single user, you need to output his name, billing month (the title ensures that all records of a single user are generated in the same month), the length and cost of effective call records, and finally output his total tariff. Note: unit conversion is required for the output of tariff. Convert cent to dollar, so the result should be divided by 100.

Input example:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10//Rate per hour interval
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

Output example:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount:$28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount:$638.80

Example explanation (take CYLL as an example):
  two pairs of paired records can be found. That is, 01:06:01(on-line) and 01:08:03(off-line), 28:15:41(on-line) and 28:16:05(off-line). The duration is 122min and 24min respectively. The cost is (20x59+20x60+20x3)/100.0=24.40, (15x19+20x5)/100.0=3.85 respectively, and the total cost is 28.25.

Idea:
(1) Step 1: first store the user name, month, day, hour, minute and call status of a single Record in the structure Record, and then sort all records according to the topic requirements:

  • If the user names are different, they are arranged from small to large according to the user name dictionary
  • Otherwise, if the months are different, they are sorted from small to large
  • Otherwise, if the dates are different, they are sorted from the smallest to the largest
  • Otherwise, if the hours are different, they are arranged from small to large
  • Otherwise, if the minutes are different, arrange them from small to large

Therefore, the comparison function can be written:

bool cmp(Record a , Record b){
    int s = strcmp(a.name , b.name);
    if(s!=0)
        return s < 0;//Priority shall be given to names in dictionary order from small to large
    else if(a.month != b.month)
        return a.month < b.month;
    else if(a.dd != b.dd)
        return a.dd < b.dd;
    else if(a.hh != b.hh)
        return a.hh < b.hh;
    else
        return a.mm < b.mm;
}

(2) Step 2: since all records are sorted according to the above function, the records of the same user are continuous in the array and stored in chronological order. You can set an int type variable needPrint to indicate whether the user has a valid. The initial value is 0. Traverse all the records of the user. If you encounter on-line when needPrint is 0, set needPrint to 1; if you encounter off-line when needPrint is 1, set it to 2. At the end of the traversal, if needPrint is 2, it indicates that the user has a valid call record. In order to process the data of multiple users, you can set the int type variable next to record the subscript of the first record of a user in the array

(3) Step 3: output valid call records. It is known from the question. It must be ensured that on-line and off-line records appear successively. Pairing can only be carried out when the difference in the following table of the array is 1

(4) Time length calculation: for the known start time and end time, just keep increasing the start time by 1 to judge whether the end time is reached

code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int toll[25]; //Rates in different time periods
struct Record{ //Call log
    char name[25];
    int month,dd,hh,mm;
    bool status;//true indicates on-line, otherwise it is off-line
}rec[maxn],temp;

bool cmp(Record a , Record b){
    int s = strcmp(a.name , b.name);
    if(s!=0)
        return s < 0;//Priority shall be given to names in dictionary order from small to large
    else if(a.month != b.month)
        return a.month < b.month;
    else if(a.dd != b.dd)
        return a.dd < b.dd;
    else if(a.hh != b.hh)
        return a.hh < b.hh;
    else
        return a.mm < b.mm;
}

void get_ans(int on ,int off , int &time , int &money){
    temp = rec[on];//Start time of this record
    while(temp.dd < rec[off].dd || temp.hh < rec[off].hh || temp.mm < rec[off].mm){
        time++;//Total time of this record plus 1
        money += toll[temp.hh];//Increase in telephone charges
        temp.mm++;
        if(temp.mm >= 60){
            temp.hh++;
            temp.mm = 0;
        }
        if(temp.hh >= 24){
            temp.dd++;
            temp.hh = 0;
        }
    }
}

int main(){
    for(int i = 0 ; i < 24 ;i++){
        scanf("%d",&toll[i]);//postage
    }
    int n;
    scanf("%d",&n);
    char line[10];//Temporarily store on-line or off-line
    for(int i = 0 ; i < n ; i++){
        scanf("%s",rec[i].name);
        scanf("%d:%d:%d:%d",&rec[i].month,&rec[i].dd,&rec[i].hh,&rec[i].mm);
        scanf("%s",&line);
        if(strcmp(line,"on-line")==0){
            rec[i].status = true;
        }else{
            rec[i].status = false;
        }
    }
    sort(rec,rec+n,cmp);
    int on = 0 , off , next;//on and off are paired records, and next is the next user
    while(on < n ){
        int needPrint = 0 ;
        next = on; //Find the next user from the current location
        while(next < n && strcmp(rec[next].name,rec[on].name)==0){
            if(needPrint == 0 && rec[next].status == true){
                needPrint = 1;
            }else if(needPrint ==1 && rec[next].status == false){
                needPrint = 2;
            }
            next++;
        }
        if(needPrint < 2){//No pair found
            on = next;
            continue;
        }
        int Allmoney = 0;//Total cost
        printf("%s %02d\n",rec[on].name,rec[on].month);
        while(on < next){
            while(on < next &&!(rec[on].status == true && rec[on+1].status ==false)){
                on++;
            }
            off = on +1;
            if(off == next){
                on = next;
                break;
            }
            printf("%02d:%02d:%02d ",rec[on].dd,rec[on].hh,rec[on].mm);
            printf("%02d:%02d:%02d ",rec[off].dd,rec[off].hh,rec[off].mm);
            int time = 0 ,money = 0;
            get_ans(on,off,time,money);
            Allmoney += money;
            printf("%d $%.2f\n",time , money/100.0);
            on = off+1;//Complete a pairing and start looking for the next pairing
        }
        printf("Total amount: $%.2f\n",Allmoney/100.0);
    }
    return 0;
}

Topics: C Algorithm