1006 Sign In and Sign Out

At the beginning of every day, the first person who signs in the computer room will unlock the door, and the last one who signs out will lock the door. Given the records of signing in's and out's, you are supposed to find the ones who have unlocked and locked the door on that day.

每天开始时,第一个在电脑房签到的人将解锁门,最后一个签退的人将锁门。给定签到和签退的记录,你需要找出当天解锁和锁门的人。

Input Specification:

Each input file contains one test case. Each case contains the records for one day. The case starts with a positive integer M, which is the total number of records, followed by M lines, each in the format:

每个输入文件包含一个测试用例。每个测试用例包含一天的记录。测试用例以一个正整数M开头,表示记录总数,接下来M行,每行格式如下:

ID_number Sign_in_time Sign_out_time

where times are given in the format HH:MM:SS, and ID_number is a string with no more than 15 characters.

其中时间格式为HH:MM:SSID_number是不超过15个字符的字符串。

Output Specification:

For each test case, output in one line the ID numbers of the persons who have unlocked and locked the door on that day. The two ID numbers must be separated by one space.

对于每个测试用例,在一行中输出解锁和锁门的人的ID号。这两个ID号必须用一个空格分隔。

Note: It is guaranteed that the records are consistent. That is, the sign in time must be earlier than the sign out time for each person, and there are no two persons sign in or out at the same moment.

注意:保证记录是一致的。也就是说,每个人的签到时间必须早于签退时间,并且没有两个人在同一时刻签到或签退。

Sample Input:

3
CS301111 15:30:28 17:00:10
SC3021234 08:00:00 11:25:25
CS301133 21:45:00 21:58:40

Sample Output:

SC3021234 CS301133

我的思路

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	char f_ID[20];
	int f_hour=23,f_minute=59,f_second=59;
	char l_ID[20];
	int l_hour=0,l_minute=0,l_second=0;
	for(int i=0;i<n;i++){
		char ID_number[20];
		char Sign_in_time[20];
		char Sign_out_time[20];
		cin>>ID_number>>Sign_in_time>>Sign_out_time;
		int hour,minute,second;
		sscanf(Sign_in_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour<=f_hour&&minute<=f_minute&&second<=f_second){
			strcpy(f_ID,ID_number);
			f_hour=hour;
			f_minute=minute;
			f_second=second;
		}
		sscanf(Sign_out_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour>=l_hour&&minute>=l_minute&&second>=l_second){
			strcpy(l_ID,ID_number);
			l_hour=hour;
			l_minute=minute;
			l_second=second;
		}
	}
	cout<<f_ID<<" "<<l_ID;
}

得分20,一个测试点没通过。检查了一下边界,是if判断的逻辑出错了。

比如最早签到时间,并设当前最早签到时间为(f_hour,f_minute,f_second)。

我们使用if更新最早签到时间时,上面if条件为:在f_hour及以前,并且f_minute及以前,f_second及以前。

这样会导致只接受三个时间信息都在最早签到时间对应时间信息以前的才算更新。

于是我们做以前改动,完善if-else条件。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	char f_ID[20];
	int f_hour=23,f_minute=59,f_second=59;
	char l_ID[20];
	int l_hour=0,l_minute=0,l_second=0;
	for(int i=0;i<n;i++){
		char ID_number[20];
		char Sign_in_time[20];
		char Sign_out_time[20];
		cin>>ID_number>>Sign_in_time>>Sign_out_time;
		int hour,minute,second;
		
		sscanf(Sign_in_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour<f_hour){
			strcpy(f_ID,ID_number);
			f_hour=hour;
			f_minute=minute;
			f_second=second;
		} 
		else if(hour=f_hour){
			if(minute<f_minute){
				strcpy(f_ID,ID_number);
				f_hour=hour;
				f_minute=minute;
				f_second=second;
			}
			else if(minute=f_minute&&second<=f_second){
				strcpy(f_ID,ID_number);
				f_hour=hour;
				f_minute=minute;
				f_second=second;
			}
		}
		
		sscanf(Sign_out_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour>l_hour){
			strcpy(l_ID,ID_number);
			l_hour=hour;
			l_minute=minute;
			l_second=second;
		} 
		else if(hour=l_hour){
			if(minute>l_minute){
				strcpy(l_ID,ID_number);
				l_hour=hour;
				l_minute=minute;
				l_second=second;
			}
			else if(minute=l_minute&&second>=l_second){
				strcpy(l_ID,ID_number);
				l_hour=hour;
				l_minute=minute;
				l_second=second;
			}
		}
	}
	cout<<f_ID<<" "<<l_ID;
}

尽管不是很优雅,但是还是AC了。不过我们也可以改进一下。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	char f_ID[20];
	int f_hour=23,f_minute=59,f_second=59;
	char l_ID[20];
	int l_hour=0,l_minute=0,l_second=0;
	for(int i=0;i<n;i++){
		char ID_number[20];
		char Sign_in_time[20];
		char Sign_out_time[20];
		cin>>ID_number>>Sign_in_time>>Sign_out_time;
		int hour,minute,second;
		
		sscanf(Sign_in_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour>f_hour);
		else if(hour==f_hour&&minute>f_minute);
		else if(hour==f_hour&&minute==f_minute&&second>f_second);
		else{
			strcpy(f_ID,ID_number);
			f_hour=hour;
			f_minute=minute;
			f_second=second;
		}
		
		sscanf(Sign_out_time,"%d:%d:%d",&hour,&minute,&second);
		if(hour<l_hour);
		else if(hour==l_hour&&minute<l_minute);
		else if(hour==l_hour&&minute==l_minute&&second<f_second);
		else{
			strcpy(l_ID,ID_number);
			l_hour=hour;
			l_minute=minute;
			l_second=second;
		}

	}
	cout<<f_ID<<" "<<l_ID;
}

南辕北辙,优雅多了。

顺利拿下!

Solution

#include <iostream>
#include <climits>
using namespace std;
int main() {
    int n, minn = INT_MAX, maxn = INT_MIN;
    scanf("%d", &n);
    string unlocked, locked;
    for(int i = 0; i < n; i++) {
        string t;
        cin >> t;
        int h1, m1, s1, h2, m2, s2;
        scanf("%d:%d:%d %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);
        int tempIn = h1 * 3600 + m1 * 60 + s1;
        int tempOut = h2 * 3600 + m2 * 60 + s2;
        if (tempIn < minn) {
            minn = tempIn;
            unlocked = t;
        }
        if (tempOut > maxn) {
            maxn = tempOut;
            locked = t;
        }
    }
    cout << unlocked << " " << locked;
    return 0;
}

可以看到,题解与我们方法的不同:

  1. 使用scanf("%d:%d:%d %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);控制输入;而我们为了复习回顾C++快速回顾重点——C语言基础(一)的内容,用的sscanf。
  2. 使用类时间戳进行运算,减少了if-else判断出错的可能性;而我们使用if-else判断,更直观。

标题:PAT 1006 签到与签退
作者:Departure
地址:https://www.unreachablecity.club/articles/2023/04/20/1682004106562.html