这一道题我是按着算法笔记上面来写的。
题目信息比较繁杂,经过思考后我觉得可以分为以下几个步骤来写:
- 建立结构体存储record记录。(基础)
- 对record的数组按照一定规则进行排序。(基础)
- 设置标志分割出同一个用户的所有record。(提高)
- 筛选不符合同时拥有上线和下线的记录。(难点)
- 在同一个用户所有符合条件的record遍历相邻的record。(提高)
- 根据分时段计费准确求出record的费用。(难点)
- 计算求出一个用户所有的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);
}
}