552. Student Attendance Record II(学生出勤记录 II)

552. Student Attendance Record II

博主看到这题时候第一感觉就是DP方法,但是想了一会方程式写不出来,然后开始怀疑是不是动态方程,想了一下过程感觉极其复杂。看了讨论区,茅塞顿开。首先讲解一下过程。首先我们定义一个问题,我们在字符串最后添加一个字符只能是以A L P三种结尾,因此定义T(n)是长度为n的所有情况。那么:
T(n) = A(n) + L(n) + P(n)代表最终是以A L P 结尾的三种情况累加。

那么我们逐个分析:
P(n)代表什么意思呢:是长度为n且以P为结尾。那么
P(n)是不是可以表示成长度为n-1 分别以A L P 结尾最后添加一个P形成n长度。

P(n) = P(n - 1) + A(n - 1)+ L(n - 1)
这个非常好理解吧。

我们来考虑L(n)情况:
同样以L结尾长度为n的情况可以分解一下,分别以长度n-1,A L P结尾的字符串最后添加一个L就形成了n长度的L(n),但是这里有一种情况不可以,也就是长度为n-1以L结尾的字符需要特殊考虑。比如AL+L可以,但是LL + L不可以。也就是我们需要考虑n-2到底是不是L。

L(n) = A(n - 1)+ P(n - 1)+(A(n - 2) + P(n - 2))

我这么写不知道大家能不能理解,也就是说将L(n - 1)当中的L(n - 2)删除,本来L(n - 1)是包含 A(n - 2)+ L (n - 2) + P (n - 2)三种,但是第二种不符合。应该明白了吧。

先来来考虑A(n),也是比较复杂的情况:

A(n)考虑长度n-1的三种情况,我们知道如果里面已经有了A那么必然不存在。我们定义 NoAL(n) 和 NoAP(n) 代表什么意思呢,就是说NoAL(n)表示长度为n以L结尾的字符串,同时不包含A。同理NoAP(n)代表长度为n以P结尾的字符串,同时不包含A。那么:

NoAL(n) = NoAP(n-1) + NoAP(n-2)

NoAP(n) = NoAL(n-1) + NoAP(n-1)

大家理解上面L(n)应该很清楚能明白上面两个式子。
那么:
A(n) = NoAL(n-1) + NoAP(n-1)
我们观察和代入可以得到下面的公式:
NoAL(n-1) = NoAP(n-2) + NoAP(n-3)
NoAP(n-1) = NoAL(n-2) + NoAP(n-2)

A(n) = A(n-1) + A(n-2) + A(n-3)
至此关系式子已经完成,需要填写一下边界,那么我们上代码:

class Solution {
public:
	int checkRecord(int n) {
		if (n == 1)
			return 3;
		if (n == 2)
			return 8;
		vector<int> A(n + 1, 0);
		vector<int> L(n + 1, 0);
		vector<int> P(n + 1, 0);
		A[1] = 1;L[1] = 1;P[1] = 1;
		A[2] = 2;A[3] = 4;
		L[2] = 3;P[2] = 3;
		for (int i = 3; i <= n; i++)
		{
			P[i] = ((A[i - 1] + L[i - 1]) % mod + P[i - 1]) % mod;
			L[i] = ((A[i - 1] + P[i - 1]) % mod + (A[i - 2] + P[i - 2]) % mod) % mod;
			if (i > 3)
				A[i] = ((A[i - 1] + A[i - 2]) % mod + A[i - 3]) % mod;
		}
		return (((A[n] % mod + L[n] % mod) % mod + P[n] % mod) % mod);
	}
private:
	static const int mod = 1000000007;
};

这是一个非常nice的题目,看到这个解题过程非常舒服。

在C++中,我们可以创建一个学生管理系统的框架,其中包含一个表示学生的类,比如`Student`,它会有一个字段来存储学生出勤状态,比如`attendanceRecord`。同时,可以定义一个用于追踪迟到情况的数据结构,例如`LateRecords`。 首先,定义`Student`类的基本结构: ```cpp class Student { public: string name; int id; vector<bool> attendanceRecord; // 使用布尔数组表示出勤,true代表出席,false代表缺席 // 添加迟到记录的方法 void recordLate(int lateTime) { LateRecords.push_back({id, lateTime}); } private: struct LateRecords { int studentId; int lateMinutes; }; }; ``` 接下来,你可以提供一些基本操作,如添加、查看出勤记录和迟到记录: ```cpp // 添加出勤记录 void attend(Student& student, bool isPresent) { student.attendanceRecord.push_back(isPresent); } // 查看学生出勤状况 void viewAttendance(const Student& student) { for (bool attendance : student.attendanceRecord) { if (attendance) cout << "学生 " << student.name << " 出席" << endl; else cout << "学生 " << student.name << " 缺席" << endl; } } // 显示迟到记录 void displayLateRecords(const Student::LateRecords& records) { cout << "迟到记录:" << endl; for (const auto& record : records) { cout << "学生ID: " << record.studentId << ", 迟到分钟数: " << record.lateMinutes << endl; } } ``` 在这个系统中,每当有新的出勤数据或迟到事件发生时,就通过相应的函数更新并处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值