#P2367. 第1题-打卡
-
1000ms
Tried: 530
Accepted: 101
Difficulty: 5
所属公司 :
华为
时间 :2023年8月30日-国内
-
算法标签>模拟
第1题-打卡
题目描述
某高科技公司为员工提供智慧打卡系统,记录员工每日的进出门禁时间。为计算员工的实际工作时长,考虑以下规则:离岗时间不超过 15 分钟的,不扣除工作时长;午休时间为 12:00 至 14:00,此时间段内不算工作时长;晚饭时间为 18:00 至 19:30,此时间段内也不算工作时长。
输入包括四行:第一行是员工当天进门禁的次数 ( n );第二行是员工当天所有的入门禁时间,以空格分隔(格式为 HH:MM);第三行是员工当天出门禁的次数 ( m );第四行是员工当天所有的出门禁时间,以空格分隔(格式为 HH:MM)。输出为员工当天的工作时长(单位:分钟)。
思路: 模拟
若离岗时间不超过15min,那么直接可以将出门禁时间改为下次入门禁时间。对于午休时间和晚饭时间,可以将入门禁时间改为午休和晚饭的结束,出门禁时间改为午休和晚饭的开始。处理后可能会存在单次打卡出门禁时间在入门禁时间之前,直接将本次工作时间置零即可。然后计算单次工作时间。
题解
我们需要计算员工的工作时长,具体考虑以下几点:
-
输入与数据结构:
- 我们首先读取员工当天的入门禁和出门禁时间。为了方便计算,使用一个
pair<int, int>的结构来存储时间(小时和分钟)。
- 我们首先读取员工当天的入门禁和出门禁时间。为了方便计算,使用一个
-
离岗时间的处理:
- 如果员工的离岗时间不超过 15 分钟,可以认为该段时间内不算离岗,因此可以将该次出门禁时间替换为下次入门禁时间。
-
午休和晚饭时间的处理:
- 午休时间为 12:00 到 14:00,晚饭时间为 18:00 到 19:30。在计算工作时长时,如果入门禁时间落在午休时间或晚饭时间内,需要调整入门禁和出门禁的时间:
- 入门禁时间调整为午休结束或晚饭结束的时间。
- 出门禁时间调整为午休开始或晚饭开始的时间。
- 午休时间为 12:00 到 14:00,晚饭时间为 18:00 到 19:30。在计算工作时长时,如果入门禁时间落在午休时间或晚饭时间内,需要调整入门禁和出门禁的时间:
-
计算有效工作时长:
- 对于每一对入门禁和出门禁时间,计算其对应的工作时长,并累加。如果出门禁时间在入门禁时间之前,则该段工作时间为 0。
代码
C++
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mr make_pair
#define fi first
#define se second
typedef pair<int, int> Pii;
// 计算两次打卡时间的差值(返回有效工作时长)
int cal(Pii p1, Pii p2) {
if (p2 <= p1) return 0; // 如果出门禁时间在入门禁时间之前,则置零
return (p2.fi - p1.fi - 1) * 60 + (60 - p1.se + p2.se);
}
int main() {
int n, mm, h, m;
cin >> n; // 读取入门禁次数
vector<Pii> s, e; // s存储入门禁时间,e存储出门禁时间
// 读取入门禁时间
for (int i = 0; i < n; i++) {
scanf("%d:%d", &h, &m);
s.pb(mr(h, m)); // 将时间存储为pair
}
cin >> mm; // 读取出门禁次数
int ans = 0; // 初始化工作时长
for (int i = 0; i < mm; i++) {
scanf("%d:%d", &h, &m);
if (i != mm - 1) {
// 如果当前出门禁时间与下一个入门禁时间的差值小于等于15分钟
if (cal(mr(h, m), s[i + 1]) <= 15) {
e.pb(s[i + 1]); // 将出门禁时间替换为下次入门禁时间
continue;
}
}
e.pb(mr(h, m)); // 存储当前出门禁时间
}
// 处理午休和晚饭的时间段
for (int i = 0; i < n; i++) {
if (s[i].fi < 14 && s[i].fi >= 12) s[i].fi = 14, s[i].se = 0; // 入门禁时间在午休期间,调整为14:00
if (s[i].fi == 18 || (s[i].fi == 19 && s[i].se <= 30)) s[i].fi = 19, s[i].se = 30; // 入门禁时间在晚饭期间,调整为19:30
}
for (int i = 0; i < mm; i++) {
if (e[i].fi < 14 && e[i].fi >= 12) e[i].fi = 12, e[i].se = 0; // 出门禁时间在午休期间,调整为12:00
if (e[i].fi == 18 || (e[i].fi == 19 && e[i].se <= 30)) e[i].fi = 18, e[i].se = 0; // 出门禁时间在晚饭期间,调整为18:00
// 计算有效工作时长并累加
ans += cal(s[i], e[i]);
}
cout << ans << endl; // 输出总工作时长
return 0;
}
java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
// 定义一个Pair类,用于存储时间的小时和分钟
static class Pair {
int fi, se; // fi代表小时,se代表分钟
Pair(int fi, int se) {
this.fi = fi; // 初始化小时
this.se = se; // 初始化分钟
}
// 比较当前时间与其他时间,判断是否小于等于
boolean lessThanOrEqualTo(Pair other) {
return this.fi < other.fi || (this.fi == other.fi && this.se <= other.se);
}
}
// 计算两次打卡时间的差值(返回有效工作时长)
static int cal(Pair p1, Pair p2) {
if (p2.lessThanOrEqualTo(p1)) return 0; // 如果出门禁时间在入门禁时间之前,则置零
// 计算工作时长
return (p2.fi - p1.fi - 1) * 60 + (60 - p1.se + p2.se);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 创建扫描器以读取输入
int n = sc.nextInt(); // 读取入门禁次数
List<Pair> s = new ArrayList<>(); // 存储入门禁时间
List<Pair> e = new ArrayList<>(); // 存储出门禁时间
// 读取入门禁时间
for (int i = 0; i < n; i++) {
String[] str = sc.next().split(":"); // 按照':'分割时间字符串
int h = Integer.parseInt(str[0]); // 解析小时
int m = Integer.parseInt(str[1]); // 解析分钟
s.add(new Pair(h, m)); // 将时间存储为Pair对象
}
int mm = sc.nextInt(); // 读取出门禁次数
int ans = 0; // 初始化工作时长
// 读取出门禁时间
for (int i = 0; i < mm; i++) {
String[] str = sc.next().split(":"); // 按照':'分割时间字符串
int h = Integer.parseInt(str[0]); // 解析小时
int m = Integer.parseInt(str[1]); // 解析分钟
// 如果不是最后一次出门禁
if (i != mm - 1) {
// 若离岗时间不超过15分钟,则将出门禁时间改为下次入门禁时间
if (cal(new Pair(h, m), s.get(i + 1)) <= 15) {
e.add(new Pair(s.get(i + 1).fi, s.get(i + 1).se)); // 使用下一个入门禁时间
continue; // 跳过当前循环
}
}
e.add(new Pair(h, m)); // 存储当前出门禁时间
}
// 处理午休和晚饭的时间段
for (int i = 0; i < n; i++) {
if (s.get(i).fi < 14 && s.get(i).fi >= 12) { // 如果入门禁时间在午休期间
s.get(i).fi = 14; // 将入门禁时间调整为14:00
s.get(i).se = 0; // 分钟部分设置为0
}
if (s.get(i).fi == 18 || (s.get(i).fi == 19 && s.get(i).se <= 30)) {
// 如果入门禁时间在晚饭期间
s.get(i).fi = 19; // 将入门禁时间调整为19:30
s.get(i).se = 30;
}
}
// 处理出门禁时间
for (int i = 0; i < mm; i++) {
if (e.get(i).fi < 14 && e.get(i).fi >= 12) { // 如果出门禁时间在午休期间
e.get(i).fi = 12; // 将出门禁时间调整为12:00
e.get(i).se = 0; // 分钟部分设置为0
}
if (e.get(i).fi == 18 || (e.get(i).fi == 19 && e.get(i).se <= 30)) {
// 如果出门禁时间在晚饭期间
e.get(i).fi = 18; // 将出门禁时间调整为18:00
e.get(i).se = 0; // 分钟部分设置为0
}
ans += cal(s.get(i), e.get(i)); // 计算有效工作时长并累加
}
System.out.println(ans); // 输出总工作时长
}
}
python
def cal(p1, p2):
# 计算两次打卡时间的差值(返回有效工作时长)
if p2 <= p1: # 处理后可能会存在单次打卡出门禁时间在入门禁时间之前,直接置零
return 0
# 计算工作时长,考虑小时和分钟的差值
return (p2[0] - p1[0] - 1) * 60 + (60 - p1[1] + p2[1])
# 读取入门禁次数
n = int(input())
s = [] # 存储入门禁时间
str = list(input().split()) # 读取入门禁时间字符串并分割
for i in range(n):
h, m = map(int, str[i].split(":")) # 将HH:MM格式的时间解析为小时和分钟
s.append((h, m)) # 存储为元组 (小时, 分钟)
# 读取出门禁次数
mm = int(input())
e = [] # 存储出门禁时间
str = list(input().split()) # 读取出门禁时间字符串并分割
for i in range(mm):
h, m = map(int, str[i].split(":")) # 将HH:MM格式的时间解析为小时和分钟
# 如果不是最后一次出门禁
if i != mm - 1:
# 若离岗时间不超过15分钟,则将出门禁时间替换为下次入门禁时间
if cal((h, m), s[i + 1]) <= 15:
e.append(s[i + 1]) # 使用下一个入门禁时间
continue # 跳过当前循环
e.append((h, m)) # 存储当前出门禁时间
# 处理午休和晚饭的时间段
for i in range(n):
if 12 <= s[i][0] < 14: # 如果入门禁时间在午休期间
s[i] = (14, 0) # 将入门禁时间调整为14:00
if s[i][0] == 18 or (s[i][0] == 19 and s[i][1] <= 30):
s[i] = (19, 30) # 将入门禁时间调整为19:30
# 处理出门禁时间
for i in range(mm):
if 12 <= e[i][0] < 14: # 如果出门禁时间在午休期间
e[i] = (12, 0) # 将出门禁时间调整为12:00
if e[i][0] == 18 or (e[i][0] == 19 and e[i][1] <= 30):
e[i] = (18, 0) # 将出门禁时间调整为18:00
# 计算总的工作时长
ans = 0
for i in range(mm):
ans += cal(s[i], e[i]) # 累加每段工作时间
print(ans) # 输出总工作时长
题目描述
某高科技公司为员工提供智慧打卡系统,记录员工每日的进出门禁时间。为计算员工的实际工作时长,考虑以下规则:离岗时间不超过 15 分钟的,不扣除工作时长;午休时间为 12:00 至 14:00,此时间段内不算工作时长;晚饭时间为 18:00 至 19:30,此时间段内也不算工作时长。
输入描述
输入包括四行:第一行是员工当天进门禁的次数 ( n );第二行是员工当天所有的入门禁时间,以空格分隔(格式为 HH:MM);第三行是员工当天出门禁的次数 ( m );第四行是员工当天所有的出门禁时间,以空格分隔(格式为 HH:MM)。
输出描述
输出为员工当天的工作时长(单位:分钟)。
样例 输入
10
02:19 06:39 07:52 14:42 16:53 18:01 19:12 20:54 22:31 23:27
10
02:45 07:17 13:37 15:52 16:56 19:10 19:21 22:15 22:34 23:38
输出
480