题123.pat甲级练习-1016 Phone Bills (25 分)(测试点1,2)
一、题目
二、题解
咳,开局我想先说一下这个搞惨我的测试点1、2,我是真的没 ?出来题目要求我不要把没消费的人给输出出来,这里就折磨了我一个钟头了,弄出来之后差点没当场去世,真的又是被pta题目测试点给搞的一天…
然后,这道题目难点于我而言有这么几个。第一,如何匹配每个人的上下线记录,我是用一个map存了每个人的记录,然后后期遍历它,去找能匹配的两条记录,这个条件便是当前记录是上线而紧跟的下一条记录是下线,由于我用string表示的时间,所以map存放后按字典排序时间轴自己也就出来了。第二,如何计算匹配的两条记录的花费,我才用的是直接计算,虽然我看好多人是得到第一条记录的花费与第二条记录的花费作差得到。
#include <bits/stdc++.h>
using namespace std;
struct Line//用一个结构体来表示一个人的上下线记录
{
string mm;//记录月份
map<string,int> line;//存上下线记录,value为1表示上线,为0表示下线
};
int main()
{
int cost[24];
for(int i=0;i<24;i++)//输入一天中每一个小时的花费
{
cin>>cost[i];
}
int N;
cin>>N;
map<string,Line> m;//用map键值对来记录一个人的信息,key表示人名(保证了以字典序存储),value表示记录
for(int i=0;i<N;i++)//保存所有记录
{
string name,line,key;
cin>>name>>line>>key;
m[name].mm=line.substr(0,2);
if(key=="on-line")
{
m[name].line[line.substr(3,8)]=1;
}
else
{
m[name].line[line.substr(3,8)]=0;
}
}
map<string,Line>::iterator it;
for(it=m.begin();it!=m.end();it++)//遍历每个人
{
int flag=1;
Line l=it->second;//拿出这个人的记录
map<string,int>::iterator it0;
float moneysum=0;
for(it0=l.line.begin();;)//遍历记录
{
//我们用是一个map存所有记录,所以我们遍历它的时候要注意的是,我们先取当前的记录,
//然后再让it0后移,去取下一个记录,只有当前记录等于1,即上线,下一条记录为0,即
//下线,我们才说两记录匹配,输出,进而去算费用,再输出
string line1=it0->first;
int key1=it0->second;
it0++;
if(it0!=l.line.end())
{
string line2=it0->first;
int key2=it0->second;
if(key1==1&&key2==0)
{
if(flag)//保证只有这个人有消费才输出它的信息,之前就是因为没顾及这个导致我测试带你1、2过不去
{
cout<<it->first<<" "<<l.mm<<endl;
flag=0;
}
//由于用的是字符串存时间,所以要找准位置截取子串转成时间,并化分钟
int start_time=(stoi(line1.substr(0,2))-1)*24*60+stoi(line1.substr(3,2))*60+stoi(line1.substr(6,2));
int over_time=(stoi(line2.substr(0,2))-1)*24*60+stoi(line2.substr(3,2))*60+stoi(line2.substr(6,2));
int distance_time=over_time-start_time;
cout<<line1<<" "<<line2<<" "<<distance_time<<" ";
//开始计算费用
//先得到开始与结束时候的日,时,分
int dd1,hh1,mm1;
dd1=stoi(line1.substr(0,2));
hh1=stoi(line1.substr(3,2));
mm1=stoi(line1.substr(6,2));
int dd2,hh2,mm2;
dd2=stoi(line2.substr(0,2));
hh2=stoi(line2.substr(3,2));
mm2=stoi(line2.substr(6,2));
int i=dd1,j=hh1,k=mm1;
float money=0;
while(1)
{
//我计算费用策略时直接算,从开始时间开始,每次加一分钟,然后适时进制,
//当日、时、分都为结束时间时退出
if(i==dd2&&j==hh2&&k==mm2)
{
break;
}
k++;
money+=cost[j];
if(k==60)
{
k=0;
j++;
}
if(j==24)
{
j=0;
i++;
}
}
moneysum+=money;
printf("$%.2f\n",money/100);
}
}
else
{
break;
}
}
if(moneysum!=0)
{
printf("Total amount: $%.2f\n",moneysum/100);
}
}
}