552. 学生出勤记录 II

214 阅读3分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

552. 学生出勤记录 II

可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符: 'A':Absent,缺勤 'L':Late,迟到 'P':Present,到场 如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:

按 总出勤 计,学生缺勤('A')严格 少于两天。 学生 不会 存在 连续 3 天或 连续 3 天以上的迟到('L')记录。 给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 109 + 7 取余 的结果。

示例 1:

输入:n = 2 输出:8 解释: 有 8 种长度为 2 的记录将被视为可奖励: "PP" , "AP", "PA", "LP", "PL", "AL", "LA", "LL" 只有"AA"不会被视为可奖励,因为缺勤次数为 2 次(需要少于 2 次)。 示例 2:

输入:n = 1 输出:3 示例 3:

输入:n = 10101 输出:183236316

解题思路

dp[n][i][j]表示前n天,缺勤i天,连续迟到j天的情况

状态转移

第n天可能产生3种情况,分别是旷课,迟到和正常出勤

  • 正常出勤:正常出勤的情况可以由以下情况转移而来(转移而来的缺勤天数i保持相同)
  1. 前一天正常出勤或者缺勤
  2. 前一天连续迟到一天
  3. 前一天连续迟到两天
  • 旷课:由缺勤天数为0的所有情况转移而来
  1. 前一天正常出勤
  2. 前一天连续迟到一天
  3. 前一天连续迟到两天
  • 迟到一天:迟到的情况可以由以下情况转移而来(转移而来的缺勤天数i保持相同)
  1. 前一天正常出勤或者缺勤
  • 迟到二天:迟到的情况可以由以下情况转移而来(转移而来的缺勤天数i保持相同)
  1. 前一天连续迟到一天

代码

class Solution {
    public int checkRecord(int n) {

        // 天数,旷课,迟到
        int[][][] dp = new int[n][2][3];
        dp[0][1][0]=1;
        dp[0][0][1]=1;
        dp[0][0][0]=1;
        int mod=1000000007;
        for (int i=1;i<n;i++){
            //------旷课--------
            //今天才旷课的
                for (int k=0;k<3;k++)
                    dp[i][1][0]=(dp[i-1][0][k]+dp[i][1][0])%mod;
                // 今天迟到的
            for (int j=0;j<2;j++)
            {
                dp[i][j][2]=dp[i-1][j][1];
                dp[i][j][1]=dp[i-1][j][0];
            }
            //今天没事的
            for (int j=0;j<2;j++)
                for (int k=0;k<3;k++)
                    dp[i][j][0]=(dp[i][j][0]+dp[i-1][j][k])%mod;
                

        }
        int res=0;
        for (int j=0;j<2;j++)
            for (int k=0;k<3;k++)
                res=(res+dp[n-1][j][k])%mod;
        return res;

    }
}