hihocoder #1482 : 出勤记录II dp

来源:互联网 发布:广东软件评测中心 编辑:程序博客网 时间:2024/05/10 07:00
描述
小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。

一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。

如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。

现在给出字符串的长度N,小Hi想知道长度为N的出勤记录中,合格的记录总共有多少种。

例如长度为3的合格出勤记录有19种:OOO OOL OOA OLO OAO LOO AOO OLL OLA OAL LOL LOA AOL LLO LAO ALO LLA LAL ALL。

输入
一个整数N(1 <= N <= 100000)。

输出
长度为N的合格记录总数。由于结果可能很大,你只需输出结果模109+7的余数。

样例输入
3
样例输出

19


思路:

dp[i][j][k] 为 长度为i的出勤记录,其中旷课j次,最后一次连续迟到的次数k,( 我们这里所说的最后一次就是指的最后一次出勤,往前一共三次出勤 连续旷课的次数)


那么我们可以得出如下的状态转移方程:

旷课的j所有取值为 0~1

最后一次连续迟到的次数k的取值0~2

我们分情况讨论,讨论边界的情况  ,

dp[i+1][j][0]+=dp[i][j][k]           //这里表示最后一次未迟到 正常上课

如果从未旷课 那么有

dp[i+1][j+1][0]=(dp[i+1][j+1][0]+dp[i][j][k])%mod;(这里k为什么成了0  好好体会一下发现 增加了一个旷课会使连续迟到次数也变为0  姑且可以这么理解)

如果连续吃到不到两次 那么有

dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k])%mod;

#include<bits/stdc++.h>#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int maxn=1e5+10;const int mod=1e9+7; int n;int dp[maxn][5][5];void init(){memset(dp,0,sizeof(dp));dp[0][0][0]=1;for(int i=0;i<=1e5;i++){for(int j=0;j<=1;j++){for(int k=0;k<=2;k++){dp[i+1][j][0]=(dp[i+1][j][0]+dp[i][j][k])%mod;if(j!=1)dp[i+1][j+1][0]=(dp[i+1][j+1][0]+dp[i][j][k])%mod;if(k!=2)c}}}return ;}int main(){init();while(~scanf("%d",&n)){int ans=0;for(int i=0;i<=1;i++) for(int j=0;j<=2;j++) ans=(ans+dp[n][i][j])%mod; printf("%d\n",ans);} return 0;}



0 0