L1-043 阅览室

天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时,管理员输入书号并按下S键,程序开始计时;当读者还书时,管理员输入书号并按下E键,程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号输入时,表示一天工作结束,你的程序应输出当天的读者借书次数和平均阅读时间。

注意:由于线路偶尔会有故障,可能出现不完整的纪录,即只有S没有E,或者只有E没有S的纪录,系统应能自动忽略这种无效纪录。另外,题目保证书号是书的唯一标识,同一本书在任何时间区间内只可能被一位读者借阅。

输入格式:

输入在第一行给出一个正整数N(≤10),随后给出N天的纪录。每天的纪录由若干次借阅操作组成,每次操作占一行,格式为:

书号([1, 1000]内的整数) 键值SE发生时间hh:mm,其中hh是[0,23]内的整数,mm是[0, 59]内整数)

每一天的纪录保证按时间递增的顺序给出。

输出格式:

对每天的纪录,在一行中输出当天的读者借书次数和平均阅读时间(以分钟为单位的精确到个位的整数时间)。

输入样例:

3
1 S 08:10
2 S 08:35
1 E 10:00
2 E 13:16
0 S 17:00
0 S 17:00
3 E 08:10
1 S 08:20
2 S 09:00
1 E 09:20
0 E 17:00

输出样例:

2 196
0 0
1 60

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

题意解析:给出n天的借书还书记录,每条记录包含书籍编号, 判定字符(字符为‘S'表示借书,字符为’E'表示还书),以及操作时间(包含时和分,但是为了便于计算,我们可以把时换算成分,然后统一记录),当书籍编号为0时表示当天记录全部输入完了,基于上述输入,我们需要对每天的数据进行统计,输出当天的借阅次数(有借有还才算完整借阅)以及平均借阅时长(总借阅时长 / 借阅次数)

注意点:

1.在输入时因为存在时间的输入(h:m),推荐使用scanf格式输入

2.对于借书可能存在有借无还或者有还无借,这种情况输入无效输入,不做处理

3.很大的坑,对于一本书,可能存在多借一还,此时借书时间按照最后一次借书计算,也可能存在多还一借,此时还书时间按照第一次还书计算

4.计算平均借阅时间需要四舍五入  

思路:使用map键值对来存储书的编号与借的时间(h * 60 + m),同一编号的重复借书因为只取最后一次,所以只需要不断覆盖即可,每次还书时,先判定有无借书记录,如果没有不做处理,跳过,如果有,则直接用本次输入的时间 - 借书记录的时间,就是该书本次的借阅时长了(同一本书可能被来回借阅,每次还书完成后删除对应的借书记录),对于当日借书平均时长的四舍五入, + 0.5处理即可。

Code:

#include
using namespace std;
const int N = 1010;
int main(){
    int n;
    cin >> n;//一共有n天
    map mp; //使用map键值对来存储数据,键对应书的id,值对应时间
    while(n -- ){
        mp.clear();//每一天数据都是独立的,清空map保障不受前面残余数据的影响  (不清理也能过全部测试点)
        int cnt = 0, s = 0;//cnt用来记录当天的借书次数, s用来记录当日借阅总时长
        int id, h, m;
        char c;
        while(true){//不知道当天到底有多少组数据,所以while判定语句直接设置为true
            scanf("%d %c %d:%d", &id, &c, &h, &m);
            if(id == 0){//如果id == 0,表示这一天的数据已经全部输入完了
                if(cnt == 0) cout << 0 << ' ' << 0 << '\n';//如果这一天没有结束,直接输出双0
                else cout << cnt << ' ' << int(1.0 * s / cnt + 0.5) << '\n';//有借书,则输出借书次数以及平均时长
                break;//跳出本轮循环
            }
            if(c == 'S') mp[id] = h * 60 + m; //如果是借书,则记录借书时间  (注意:由于可能存在重复借阅,但是我们只按照最后一次借阅时间计算,所以直接覆盖即可)
            else//如果是还书,则判定一下有没有借书记录,没有则不管,有则视作一次完整借阅,次数 + 1, 借阅时长对应增加
                if(mp.count(id)) { //判定id为键的键值对是否存在
                    cnt ++ ;
                    s += h * 60 + m - mp[id];//由于我们记录了借书时间,所以直接拿当前时间 - 借书时间就是该书的借阅时长了
                    mp.erase(id);//对于已经完成借阅的书籍记录,直接删除即可
                }
        }
    }
    return 0;
}

L1-043 阅览室_第1张图片

你可能感兴趣的:(天梯赛练习集,c++,团体程序设计天梯赛)