#P3036. 考勤信息(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 287
            Accepted: 51
            Difficulty: 4
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>模拟          
 
考勤信息(100分)
思路:滑动窗口模拟
维护一个长度为7的窗口,并统计其缺勒/迟到/早退次数是否超过3,维护一个变量,统计其缺勤次数,并在所有下标>0的位置判断是否有连续的迟到/早退,如果都没有,则返回true,有任意一点不满足,返回false。写的时候最好写一个判断函数,这样会方便一些。
JavaScript
// 引入readline模块
const readline = require('readline');
// 创建readline接口,设置输入和输出
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
// 定义考勤信息映射
const mp = {
    "absent": 0,
    "late": 1,
    "leaveearly": 2,
    "present": 3
};
// 定义检查函数,判断考勤信息是否合法
function check(s) {
    // 统计每种考勤状态出现的次数
    const cnts = Array(4).fill(0);
    const m = s.length;
    // 遍历考勤信息
    for (let i = 0; i < m; i++) {
        // 增加当前考勤状态的计数
        cnts[mp[s[i]]]++;
        // 如果考勤信息长度超过7,减少七天前的考勤状态计数
        if (i > 6) {
            cnts[mp[s[i - 7]]]--;
        }
        // 如果考勤信息长度大于等于7,并且正常上班天数小于4,返回false
        if (i >= 6 && cnts[3] < 4) {
            return false;
        }
        // 如果不是第一个考勤信息,并且连续两天都是迟到或早退,返回false
        if (i > 0 && 1 <= mp[s[i]] && mp[s[i]] <= 2 && 1 <= mp[s[i - 1]] && mp[s[i - 1]] <= 2) {
            return false;
        }
    }
    // 统计所有缺勤的次数
    let count = 0;
    for (const x of s) {
        if (mp[x] === 0) {
            count++;
        }
    }
    // 缺勤次数不超过1时返回true,否则返回false
    return count <= 1;
}
// 初始化变量
let n;  // 测试用例数量
let currentTest = 0;  // 当前测试用例序号
// 监听输入的每一行
rl.on('line', (line) => {
    if (!n) {
        // 第一行输入为测试用例数量
        n = parseInt(line);
    } else {
        // 处理后续测试用例
        const s = line.split(' ');
        // 调用check函数检查考勤信息是否合法,并输出结果
        if (check(s)) {
            console.log("true");
        } else {
            console.log("false");
        }
        // 增加当前测试用例序号,当序号达到测试用例数量时关闭rl接口
        currentTest++;
        if (currentTest === n) {
            rl.close();
        }
    }
});
Java
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.nextLine(); // 消耗掉换行符
        while (n-- > 0) {
            String[] s = scanner.nextLine().split(" ");
            if (check(s)) {
                System.out.println("true");
            } else {
                System.out.println("false");
            }
        }
    }
    static boolean check(String[] s) {
        int[] cnts = new int[4];
        int m = s.length;
        // 初始化考勤信息映射
        Map<String, Integer> mp = new HashMap<>();
        mp.put("absent", 0);
        mp.put("late", 1);
        mp.put("leaveearly", 2);
        mp.put("present", 3);
        for (int i = 0; i < m; i++) {
            cnts[mp.get(s[i])]++;
            if (i > 6) {
                cnts[mp.get(s[i - 7])]--;
            }
            if (i >= 6 && cnts[3] < 4) {
                return false;
            }
            if (i > 0 && 1 <= mp.get(s[i]) && mp.get(s[i]) <= 2 && 1 <= mp.get(s[i - 1]) && mp.get(s[i - 1]) <= 2) {
                return false;
            }
        }
        int count = 0;
        for (String x : s) {
            if (mp.get(x) == 0) {
                count++;
            }
        }
        return count <= 1;
    }
}
Python
mp={"absent":0,"late":1,"leaveearly":2,"present":3}  #出勤信息映射
def check(s):
    cnts=[0]*4  #统计每一项的次数
    m=len(s)
    for i in range(m):
        cnts[mp[s[i]]]+=1
        if i>6: 
            cnts[mp[s[i-7]]]-=1
        if i>=6 and cnts[3]<4:  #正常上班天数<4,则说明其他天数超过3次
            return False
        if i and 1<=mp[s[i]]<=2 and 1<=mp[s[i-1]]<=2:  #连续的迟到,早退
            return False
    count=0  #单独统计所有的缺勤次数
    for x in s:
        if mp[x]==0:
            count+=1
    return count<=1
    
n=int(input())
for _ in range(n):
    s=input().split(' ')
    if check(s):
        print("true")
    else:
        print("false")
C++
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
// 定义考勤信息映射
unordered_map<string, int> mp = {{"absent", 0}, {"late", 1}, {"leaveearly", 2}, {"present", 3}};
// 检查考勤信息是否合法的函数
bool check(const vector<string>& s) {
    // 统计每种考勤状态出现的次数
    vector<int> cnts(4, 0);
    int m = s.size();
    // 遍历考勤信息
    for (int i = 0; i < m; i++) {
        // 增加当前考勤状态的计数
        cnts[mp[s[i]]]++;
        // 如果考勤信息长度超过7,减少七天前的考勤状态计数
        if (i > 6) {
            cnts[mp[s[i - 7]]]--;
        }
        // 如果考勤信息长度大于等于7,并且正常上班天数小于4,返回false
        if (i >= 6 && cnts[3] < 4) {
            return false;
        }
        // 如果不是第一个考勤信息,并且连续两天都是迟到或早退,返回false
        if (i > 0 && 1 <= mp[s[i]] && mp[s[i]] <= 2 && 1 <= mp[s[i - 1]] && mp[s[i - 1]] <= 2) {
            return false;
        }
    }
    // 统计所有缺勤的次数
    int count = 0;
    for (const string& x : s) {
        if (mp[x] == 0) {
            count++;
        }
    }
    // 缺勤次数不超过1时返回true,否则返回false
    return count <= 1;
}
int main() {
    int n;
    cin >> n;
    cin.ignore(); // 消耗掉换行符
    // 处理每个测试用例
    while (n--) {
        string line;
        getline(cin, line);
        vector<string> s;
        // 分割字符串得到考勤信息
        size_t pos = 0, next;
        while ((next = line.find(' ', pos)) != string::npos) {
            s.push_back(line.substr(pos, next - pos));
            pos = next + 1;
        }
        s.push_back(line.substr(pos));
        // 调用check函数检查考勤信息是否合法,并输出结果
        if (check(s)) {
            cout << "true" << endl;
        } else {
            cout << "false" << endl;
        }
    }
    return 0;
}
        题目描述
公司用一个字符串来表示员工的出勤信息
- absent:缺勒
 - late: 迟到
 - leaveearly: 早退
 - present: 正常上班
 
现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下:
- 缺勤不超过一次,
 - 没有连续的迟到/早退:
 - 任意连续7次考勤,缺勒/迟到/早退不超过3次
 
输入描述
第一行输入一个整数n,表示有多少个员工
后面n行,每一行输入若干个字符串,表示第i名员工的出勤信息
输出描述
输出n行,每一行表示这名员工能否获得出勤奖,如果可以,则输出“true",否则输出”false"
样例1
输入
2
present
present present
输出
true
true
样例2
输入
2
present
present absent present present leaveearly present absent
输出
true
false