首页 > 试题广场 >

开门人和关门人

[编程题]开门人和关门人
  • 热度指数:8279 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
    每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签到、签离记录,请根据记录找出当天开门和关门的人。

输入描述:
 
    每天的记录在第一行给出记录的条目数M (M > 0 ),下面是M行,每行的格式为 

    证件号码 签到时间 签离时间 

    其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。


输出描述:
    对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。 
    注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前,且没有多人同时签到或者签离的情况。
示例1

输入

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

输出

SC3021234 CS301133

简单易懂的C语言解法

#include<stdio.h>

char IDS[100][20];

int main()
{
    int M;
    while (scanf("%d", &M) != EOF)
    {
        int Max = 0;
        int maxId = 0;
        int Min = 0x7FFFFFFF;
        int minId = 0;
        for (int i = 0; i < M; i++)
        {
            scanf("%s", IDS[i]);
            int h, m, s;
            scanf("%d:%d:%d", &h, &m, &s);
            int time = h * 3600 + m * 60 + s;
            if (time < Min) 
            {
                Min = time;
                minId = i;
            }
            scanf("%d:%d:%d", &h, &m, &s);
            time = h * 3600 + m * 60 + s;
            if (time > Max) 
            {
                Max = time;
                maxId = i;
            }
        }
        printf("%s %s\n", IDS[minId], IDS[maxId]);
    }
    return 0;
}
发表于 2019-09-09 18:48:43 回复(0)
以后有此类问题都可以用结构体数组加qsort解决(神奇的是strcmp能比较时间的字符串,不过本来就是有序的)。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct record
{
    char id[20];
    char reg[20];
    char leave[20];
}record;
int cmp0(record *a,record *b)
{
    return strcmp(a->reg,b->reg);
}
int cmp1(record *a,record *b)
{
    return strcmp(b->leave,a->leave);
}
int main()
{
    int n,i;
    while(scanf("%d",&n)!=EOF)
    {
        record r[n];
        for(i=0;i<n;i++)scanf("%s%s%s",r[i].id,r[i].reg,r[i].leave);
        qsort(r,n,sizeof(record),cmp0);
        printf("%s ",r[0].id);
        qsort(r,n,sizeof(record),cmp1);
        printf("%s\n",r[0].id);
    }
}

发表于 2020-02-13 20:36:29 回复(0)
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

struct P {
    string id;
    string come;
    string exit;
};

bool cmp1(P p1, P p2) {
    return p1.come < p2.come;
}

bool cmp2(P p1, P p2) {
    return p1.exit > p2.exit;
}

int main()
{
    int m;
    while(cin>>m) {
        P p[1000];
        for(int i = 0; i < m; i++) {
            cin>>p[i].id>>p[i].come>>p[i].exit;
        }
        sort(p, p+m, cmp1);
        cout<<p[0].id<<" ";
        sort(p, p+m, cmp2);
        cout<<p[0].id<<endl;
    }
    return 0;
}
发表于 2018-03-25 20:18:14 回复(2)
 import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class Main {
    public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        for (int i = 0; i < N; i++) {
            int m = sc.nextInt();
            String[] records = new String[m+1];
            for (int j = 0; j < m+1; j++) {
                records[j] = sc.nextLine();
            }

            String[] record ;
            Date early,late;
            DateFormat df = new SimpleDateFormat("HH:mm:ss");
            String first=null,last=null ;
            try {
                early = df.parse("23:59:59");
                late = df.parse("00:00:00");
                for (int j = 1; j < m+1; j++) {
                    record = records[j].split(" ");
                    if(early.compareTo(df.parse(record[1]))>0){
                        early = df.parse(record[1]);
                        first = record[0];
                    }
                    if(late.compareTo(df.parse(record[2]))<0){
                        late = df.parse(record[2]);
                        last = record[0];
                    }
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
            System.out.println(first+" "+last);
        }
    }
}
编辑于 2017-04-17 19:39:10 回复(0)
//思路:将数据分别放进两个优先队列中
//一个存升序,存最早进入的;一个降序,存最后离开的
#include <iostream>
#include <cstdio>
#include <queue>
#include <string>


using namespace std;
struct Enter{
    string id;
    string entertime;
    Enter(string a,string b):id(a),entertime(b){}
    bool operator> (Enter e) const{
        return entertime>e.entertime;
    }
};

struct Leave{
    string id;
    string leavetime;
    Leave(string a,string b):id(a),leavetime(b){}
    bool operator< (Leave e) const{
        return leavetime<e.leavetime;
    }
};

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        priority_queue<Enter,vector<Enter>,greater<Enter>>enter;//改为二叉小根堆
        priority_queue<Leave>leave;
        string number;
        string time1;
        string time2;
        for(int i=0;i<n;i++){
            cin>>number>>time1>>time2;
            enter.push({number,time1});
            leave.push({number,time2});
        }
        cout<<enter.top().id<<" "<<leave.top().id<<endl;
    }
    return 0;
}

发表于 2022-03-26 22:43:27 回复(0)
不知道我这样对还是不对
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

struct people{
    string number;
    string time1;
    string time2;
};
int cmp1(people x,people y)
{
    return x.time1<y.time1;
}
int cmp2(people x,people y)
{
    return x.time2>y.time2;
}
int main()
{
    struct people a[1000];
    int m;
    cin>>m;
    for(int i=0;i<m;i++)
    {
        cin>>a[i].number>>a[i].time1>>a[i].time2;
    }
    sort(a,a+m,cmp1);
    cout<<a[0].number<<" ";
    sort(a,a+m,cmp2);
    cout<<a[0].number<<endl;
    return 0;
}

发表于 2021-02-03 17:29:32 回复(0)
直接字符串比较
#include <iostream>

#include <map>
#include <vector>
#include <algorithm>

using namespace std;
struct Student {
    string ID;
    string startDate;
    string endDate;
};


bool compareByStartDate(Student &s1, Student &s2) {
    return s1.startDate < s2.startDate;
}

bool compareByEndDate(Student &s1, Student &s2) {
    return s1.endDate < s2.endDate;
}

int main() {
    int M;
    cin >> M;
    int i = M;
    vector<Student> vc;
    while (i--) {
        string id, startDate, endDate;
        cin >> id >> startDate >> endDate;
        Student s = {id, startDate, endDate};
        vc.push_back(s);
    }
    sort(vc.begin(), vc.end(), compareByStartDate);
    cout << vc[0].ID << " ";
    sort(vc.begin(), vc.end(), compareByEndDate);
    cout << vc[M - 1].ID;
    return 0;
}


发表于 2021-01-13 17:25:48 回复(0)
map底层红黑树自带排序,功能强大
#include <bits/stdc++.h>
using namespace std;

int main(){
    int m;
    cin >> m;
    getchar();
    map<string, string> M1;
    map<string, string> M2;
    while(m--){
        string str;
        getline(cin, str);
        int pos1 = str.find(' ');
        string name = str.substr(0, pos1);
        M1[str.substr(pos1+1, 8)] = name;
        M2[str.substr(pos1+10)] = name;
    }
        map<string, string>::iterator it1;
        map<string, string>::iterator it2;
        it1 = M1.begin();
        it2 = M2.end();
        cout << it1->second << " " << (--it2)->second << endl;

    return 0;
}

发表于 2020-03-23 19:52:18 回复(1)
#include<iostream>
#
include<cstdio>
#include<map>
#
include<string>
using namespace std;
int main(){
    int n;
    string number,time;
    map<string,string> To,Leave;
    while(scanf("%d",&n)!=EOF){
        To.clear();
        Leave.clear();
        for(int i=0;i<n;i++){
            cin>>number;
            cin>>time;
            To.insert(pair<string,string>(time,number));
            cin>>time;
            Leave.insert(pair<string,string>(time,number));
        }
        map<string,string>::iterator it1=To.begin();
        map<string,string>::reverse_iterator it2=Leave.rbegin();
        cout<<it1->second<<" "<<it2->second<<endl;
    }
    return 0;
}
发表于 2020-03-20 16:30:24 回复(0)
这题的输入跟代理服务器那题很像
可以将时间转换成秒数,这样比较起来更简单
个人觉得没必要排序,直接输入一个比较一个就行,时间复杂度为O(n)
#include <stdio.h>
#include <string.h>
int main() {
    int n;
    while(scanf("%d",&n)!=EOF) {
        char id[16],former[16],latter[16];
        int h1,m1,s1,h2,m2,s2,s,earliest=86400,latest=0;
        for(int i=0; i<n; i++) {
            scanf("%s%d:%d:%d%d:%d:%d",id,&h1,&m1,&s1,&h2,&m2,&s2);
            s=h1*3600+m1*60+s1;
            if(s<earliest) {
                earliest=s;
                strcpy(former,id);
            }
            s=h2*3600+m2*60+s2;
            if(s>latest) {
                latest=s;
                strcpy(latter,id);
            }
        }
        printf("%s %s\n",former,latter);
    }
    return 0;
}

编辑于 2020-03-19 20:44:55 回复(0)
Java 解法
import java.util.Scanner;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        TreeMap<String, String> open = new TreeMap<>();
        TreeMap<String, String> close = new TreeMap<>();
        for (int i = 0; i < n; i++) {
            String id = scanner.next();
            open.put(scanner.next(),id);
            close.put(scanner.next(),id);
        }
        System.out.println(open.firstEntry().getValue()+" "+close.lastEntry().getValue());

    }
}


发表于 2020-03-08 22:58:31 回复(0)
#include <iostream>
using namespace std;
int main()
{
	int n; while (cin >> n)
	{
		string open, close, id; int hs0, ms0, ss0, hs1, ms1, ss1, open_time = 24*3600, close_time = 0; char delimit0, delimit1, delimit2, delimit3;
		while (n-- && cin>>id>>hs0>>delimit0>>ms0>>delimit1>>ss0>>hs1>>delimit2>>ms1>>delimit3>>ss1)
		{
			int arrive_time = hs0 * 3600 + ms0 * 60 + ss0, leave_time = hs1 * 3600 + ms1 * 60 + ss1;
			if (open.empty() || arrive_time <= open_time) { open = id; open_time = arrive_time; }
			if (close.empty() || leave_time >= close_time) { close = id; close_time = leave_time; }
		}
		cout << open << ' ' << close << endl;
	}
	return 0;
}

发表于 2020-02-21 03:58:36 回复(0)
时间直接用string存,然后比较字符的大小即可。

#include
using namespace std;
struct stu{
    string name,in,out;
}E[10005];
bool cmp(stu a, stu b){
    return a.in < b.in;
}
bool cmp1(stu a, stu b){
    return a.out > b.out;
}
int main(){
    int n;
    string name,h,m,s,hh,mm,ss; 
     while(cin>>n){
         for(int i=0;i<n;i++){
             cin>>E[i].name>>E[i].in>>E[i].out;
         }
        sort(E,E+n,cmp);
        cout<<E[0].name<<" ";
        sort(E,E+n,cmp1);
        cout<<E[0].name<<endl;
     }

    return 0;
}
编辑于 2019-07-31 12:30:04 回复(0)
try:
    while True:
        num = int(input())
        idNum = []
        signIn = []
        signOut = []
        for i in range(num):
            temp = input().split()
            idNum.append(temp[0])
            signIn.append(temp[1])
            signOut.append(temp[2])
        a = idNum[signIn.index(min(signIn))]    #找出签到的最小值
        b = idNum[signOut.index(max(signOut))]  #找出签退的最大值
        print("%s %s" % (a,b))

except Exception:
    pass
编辑于 2018-09-20 18:15:00 回复(0)
//取巧使用map的字典序和映射特性
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[]) {
  std::map<string, string> open;
  std::map<string, string> close;
  string tmp1,tmp2,tmp3;
  int n,i;
  while (cin>>n) {
    /* code */
        for ( i = 0; i < n; i++) {
          /* code */
          cin>>tmp1>>tmp2>>tmp3;
          open.insert(pair<string,string>(tmp2,tmp1));
          close.insert(pair<string,string>(tmp3,tmp1));
        }
        cout<<open.begin()->second;
        cout<<' ';
        cout<<close.rbegin()->second;
  }
  return 0;
}
发表于 2018-07-08 17:58:25 回复(8)
#include<iostream>
#include<cstring>
using namespace std;
struct people
{
    char number[16];//证件号
    char time_start[10];//签到时间
    char time_end[10];//离开时间
};
int main()
{
    int n;
    people peo[100];
    char open_time[10], close_time[10];
    cin >> n;
    for (int i = 0; i < n; i++)//输入信息
        cin >> peo[i].number >> peo[i].time_start >> peo[i].time_end;
    strcpy(open_time, peo[0].time_start);
    strcpy(close_time, peo[0].time_end);
    for (int i = 1; i < n; i++)//寻找时间
    {
        if(strcmp(open_time,peo[i].time_start)>0)
            strcpy(open_time, peo[i].time_start);
        if(strcmp(close_time, peo[i].time_end)<0)
            strcpy(close_time, peo[i].time_end);
    }
    for (int i = 0; i < n; i++)//输出开门
    {
        if (strcmp(open_time, peo[i].time_start) == 0)
            cout << peo[i].number << " ";
    }
    for (int i = 0; i < n; i++)//输出关门
    {
        if (strcmp(close_time, peo[i].time_end) == 0)
            cout << peo[i].number <<endl;
    }
    return 0;
}
我使用的是字符串的比较,即把形如07:30:20这种直接放进字符串中,再使用strcmp进行比较
发表于 2018-07-11 18:57:51 回复(0)
//这道题有个大坑啊,我一开始觉得既然签到和签退时间不一样,就把签到和签退时间都放在了一个MAP中,过了样例提交发现过了40%
//查看错误数据后发现竟然有人在那过夜了(他的签退时间可能会早过其他人的签到时间)导致不能按照一个MAP中关键字最小最大的来选开门和关门人,我也是醉了,
//必须要把签到时间和签退时间分成两个MAP,才能找出签到最早的和签退最晚的

#include<bits/stdc++.h>
using namespace std;
map<string,string>m1;//存放签到时间和签到人关系
map<string,string>m2;//存放签退时间和签到人关系
int main()
{
    int m;
    while(cin>>m)
    {
        while(m--)
        {
            string str,str1,str2;
            cin>>str>>str1>>str2;
            m1[str1]=str;
            m2[str2]=str;
        }
        map<string,string>::iterator it;
        it=m1.begin();
        cout<<it->second<<" ";
        it=m2.end();
        it--;
        cout<<it->second<<endl;
    }
    return 0;
}

发表于 2020-04-02 16:44:31 回复(11)
#include<stdio.h>//直接字典字符顺序比较
struct jifang{
    char name[20];//证件
    char lai[20];//开
    char zou[20];//关
}work[100];
int main()
{
    int n,i,minindex,maxindex;char min[20],max[20];
    scanf("%d",&n);
    for(i=0;i<n;i++)//输入
        scanf("%s%s%s",work[i].name,work[i].lai,work[i].zou);
    strcpy(min,work[0].lai);strcpy(max,work[0].zou);//全部初始化成第一个人
    minindex=0;maxindex=0;
    for(i=0;i<n;i++)//比较
    {
        //开门人lai min
        if(strcmp(work[i].lai,min)<0)
        {
            strcpy(min,work[i].lai);
            minindex=i;
        }
        //关门人zou max
        if(strcmp(work[i].zou,max)>0)
        {
            strcpy(max,work[i].zou);
            maxindex=i;
        }
    }
    printf("%s %s",work[minindex].name,work[maxindex].name);
}

编辑于 2020-04-13 21:22:41 回复(0)
#include <cstdio>
#include <iostream>
#include <map>

using namespace std;

map<string, string> student;
 
// 寻找最早的、最晚的 
int main() {
	int n;
	scanf("%d", &n);
	getchar();// 吃掉回车 
	
	// 输入数据 
	for (int i = 0; i < n; i++) {
		string str;
		getline(cin, str);
		int m = str.find(" ");
		string num = str.substr(0, m);
		student[num] = str.substr(m+1);// 学号为主键 
	}
	string early = student.begin()->second;// 用于记录最早的时间 
	string last = student.begin()->second;// 用于记录最晚的时间 
	
	map<string, string>::iterator it;// 迭代器
	for (it = student.begin(); it != student.end(); it++) {
		int pos = it->second.find(" ");// 找到时间序列中的 “ ”,方便分割 
		
		// 分割为 开始时间 和 结束时间 
		string stime = it->second.substr(0, pos);
		string etime = it->second.substr(pos+1);
		
		// 比较时间大小 
		if (stime < early.substr(0, pos)) {
			early = it->second;
		}
		if (etime > last.substr(pos+1)) {
			last = it->second;
		}
	}
	// 找到最早的 
	for (it = student.begin(); it != student.end(); it++) {
		if (early == it->second) {
			cout << it->first << " ";
		}
	}
	
	// 找到最晚的 
	for (it = student.begin(); it != student.end(); it++) {
		if (last == it->second) {
			cout << it->first;
		}
	}
	
}

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

发表于 2023-03-27 10:45:30 回复(0)
用map的自排序
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;

int main(){
    int n;
    while(scanf("%d",&n)!=-1){
        map<string,string> in,out; 
        string name,t1,t2;
        while(n--){
            cin>>name>>t1>>t2;
            in[t1]=name;
            out[t2]=name;
        }
        
        cout<<in.begin()->second<<" "<<out.rbegin()->second;
    }
    return 0;
}


发表于 2023-03-22 16:21:44 回复(0)