PTA 团队天梯赛║L1-043 阅览室

一、题目要求

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

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

输入格式:

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

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

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

输出格式:

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

输入样例:

1
2
3
4
5
6
7
8
9
10
11
12
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

输出样例:

1
2
3
2 196
0 0
1 60

二、解题思路

因为有可能会有书未被借出就还书的错误情况,而且要记录平均平均阅读时间,因此用一个结构体存储书籍借出情况 flag (0 为未借出,1 为借出),以及借出时间 starttime 。在判断键入时,若书号键入 0 则跳出当日的输入循环,否则判断键值 S 时写入借出时间,借书计数加一;判断键值 E 时,该书号 flag 若为 0 则忽略,若为 1 则将还书时间减去借出时间作为借阅时间加入本日的阅览总时间,并将 flag 置为 0。最后计算平均借阅时间,输出借书计数与平均借阅时间即可。

三、代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <bits/stdc++.h>
using namespace std;

typedef struct Book
{
bool flag; //0 为未被借出,1 为借出
int starttime; //借出时间
}book;

int gettime(int h, int m)
{
return h*60 + m;
}

int main()
{
int n;
cin >> n;
Book b[1001];
double sumtime; //最后要四舍五入取 double 类型
int num, h, m, count; //书号,结束时间的时与分,每日的借书数量
char c; //键值
for(int i=0; i<n; i++)
{
memset(b,0,sizeof(Book)*1001); //初始化结构体,新的一天将所有书本状态归零
sumtime = 0; //新的一天阅览总时间归零
count = 0; //每日借书数量归零
while(scanf("%d %c %d:%d",&num,&c,&h,&m))
{
if(num==0) break;
if(c == 'S')
{
b[num].starttime = gettime(h,m);
b[num].flag = 1;
}
if(c == 'E')
{
if(b[num].flag == 1)
{
sumtime += gettime(h,m)-b[num].starttime;
b[num].flag = 0;
count++;
}
else
continue;
}
}
if(count == 0)
{
printf("0 0\n");
}
else
{
int averge = round(sumtime/count);
printf("%d %d\n",count,averge);
}

}

return 0;
}

四、反思总结

  1. void *memset(void *s, int c, size_t n)

    memset:作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法。

    一定要记住 如果要把一个 char a[20] 清零, 一定是 memset(a, 0, 20)
    而不是 memset(a, 20, 0)

  2. 注意本题容易出现 浮点错误 ,即有可能除数为 0 ,要注意将这一特殊情况分开讨论。

  3. 起初部分测试点结果一直差一,是因为整型数据除法计算直接保留整数,为了让结果四舍五入,将数据类型改为 double ,然后使用 round() 函数实现计算结果四舍五入。