题目描述
知识点
排序
实现
码前思考
2. 由于经过了按名字排序,所以相同的用户一定在一起,那么就可以进行on和off的匹配了,匹配就是一个比较easy思考的问题了,主要是代码比较复杂;
代码实现
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
const int maxn = 1e3+10;
int rate[30];
int n;
int dayRate=0;
int month;
struct call{
string name;
bool isOn;
int dd;
int hh;
int mm;
}calls[maxn];
bool cmp(call a,call b){
if(a.name != b.name){
return a.name < b.name;
}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;
}
}
}
}
int main(){
for(int i=0;i<24;i++){
scanf("%d",&rate[i]);
dayRate += rate[i];
}
//printf("dayRate:%d\n",dayRate);
scanf("%d",&n);
for(int i=0;i<n;i++){
string name;
int dd;
int hh;
int mm;
string status;
cin>>name;
scanf("%d:%d:%d:%d",&month,&dd,&hh,&mm);
cin>>status;
calls[i].name = name;
calls[i].dd = dd;
calls[i].hh = hh;
calls[i].mm = mm;
if(status == "on-line"){
calls[i].isOn = true;
}else{
calls[i].isOn = false;
}
}
//排序
sort(calls,calls+n,cmp);
// for(int i=0;i<n;i++){
// cout<<calls[i].name<<" "<<calls[i].dd<<" "<<calls[i].hh<<" "<<calls[i].mm<<endl;
// }
//然后遍历每一组名字相同的,寻找匹配的时间
int idx = 0; //从第0个开始
int tot = 0;
string preName = "yc"; //表示是否是重新开始的
//好坑啊
while(idx < n-1){ //不能是最后一个!最后一个会被提前匹配
//发现匹配直接进行输出了
int cur = 0; //表示当前匹配call计费
if(calls[idx].isOn == true){
if(calls[idx].name == calls[idx+1].name){
if(calls[idx+1].isOn == false){
//而且是挂线
//计算时间
int sdd = calls[idx].dd;
int edd = calls[idx+1].dd;
int shh = calls[idx].hh;
int ehh = calls[idx+1].hh;
int smm = calls[idx].mm;
int emm = calls[idx+1].mm;
int last = 0;
if(sdd != edd){
//那么要计算一下跳天总数
cur += (edd-sdd-1) * dayRate * 60;
last += (edd-sdd-1) * 60 * 24;
int scnt=0;
int ecnt=0;
//计算scnt
scnt += rate[shh] * (60-smm);
last += (60-smm);
for(int j=shh+1;j<24;j++){
scnt += rate[j] * 60;
last += 60;
}
//计算ecnt
for(int j=0;j<ehh;j++){
ecnt += rate[j] * 60;
last += 60;
}
ecnt += rate[ehh] * (emm);
last += emm;
//累加
cur += scnt;
cur += ecnt;
}else{
//在同一天
//判断是否在同一个小时
if(shh == ehh){
cur += rate[shh] * (emm - smm);
last += (emm - smm);
}else{
cur += rate[shh] * (60-smm);
last += (60-smm);
for(int j=shh+1;j<ehh;j++){
cur += rate[j] * 60;
last += 60;
}
cur += rate[ehh] * emm;
last += emm;
}
}
//输出
//如果之前输出过了
if(calls[idx].name == preName){
//那么累加
printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n",sdd,shh,smm,edd,ehh,emm,last,1.0*cur/100);
tot += cur;
}else{
//输出上次tot
if(preName != "yc"){
printf("Total amount: $%.2f\n",1.0*tot/100);
}
preName = calls[idx].name;
printf("%s %02d\n",calls[idx].name.c_str(),month);
printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n",sdd,shh,smm,edd,ehh,emm,last,1.0*cur/100);
tot = cur;
}
//两次加加,其实一次也行
idx++;
idx++;
}else{
//说明不是挂线
idx++;
}
}else{
//直接下一步
idx++;
}
}else{
//说明是挂线,这个判断很重要
idx++;
}
}
printf("Total amount: $%.2f\n",1.0*tot/100);
return 0;
}
码后反思
- 之前将
while(idx < n-1)
写成了while(idx != n-1)
导致测试点1段错误,好坑啊; - 算法笔记上的解法非常暴力,居然是让程序一步步加分钟的!这样虽然暴力,但是确实比我这个要好写多了。。。