Leetcode 552.学生出勤记录‖ 动态规划+容斥
生活随笔
收集整理的這篇文章主要介紹了
Leetcode 552.学生出勤记录‖ 动态规划+容斥
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:傳送門
可以用字符串表示一個學生的出勤記錄,其中的每個字符用來標記當天的出勤情況(缺勤、遲到、到場)。記錄中只含下面三種字符:
'A':Absent,缺勤
'L':Late,遲到
'P':Present,到場
如果學生能夠 同時 滿足下面兩個條件,則可以獲得出勤獎勵:按總出勤計,學生缺勤('A')嚴格 少于兩天。
學生 不會 存在 連續 3 天或 連續 3 天以上的遲到('L')記錄。
給你一個整數 n ,表示出勤記錄的長度(次數)。請你返回記錄長度為 n 時,可能獲得出勤獎勵的記錄情況 數量 。答案可能很大,所以返回對 1e9 + 7 取余的結果。
?自己琢磨了半天寫了一個DP+容斥,回頭一看題解,好家伙dp方程完全不一樣,還以不用容斥,還可以用矩陣快速冪搞,直接把復雜度優化到LogN,點贊。
const long long mod=1e9+7;
class Solution {
public:int checkRecord(int n) {if(n==1) return 3;if(n==2) return 8; long long dp[100005][3][2];/*第二維選擇的狀態,0=P 1=L 2=A,第三維表示是否選了1dp[i][0][0] = 當前位置i選擇了P,并且0~i之前沒有一次A缺勤的所有可能數dp[i][0][1] = 當前位置i選擇了P,并且0~i剛好有一次A缺勤的所有可能數dp[i][1][0] = 當前位置i選擇了L,并且0~i之前沒有一次A缺勤的所有可能數dp[i][1][1] = 當前位置i選擇了L,并且0~i剛好有一次A缺勤的所有可能數dp[i][2][1] = 當前位置i選擇了A,并且0~i剛好有一次A缺勤的所有可能數,選擇A就肯定有A,所有不考慮dp[i][2][0]*///初始狀態dp[0][0][0]=1;//Pdp[0][0][1]=0;//dp[0][1][0]=1;//Ldp[0][1][1]=0;//dp[0][2][1]=1;//A dp[1][0][0]=2;//PP,LPdp[1][0][1]=1;//APdp[1][1][0]=2;//PL,LLdp[1][1][1]=1;//ALdp[1][2][1]=2;//PA,LA long long sum_L0=0,sum_L1=0;for(int i=2;i<n;i++){//當前位置選P,可以由上一個推導過來dp[i][0][0]=(dp[i-1][0][0]+dp[i-1][1][0])%mod;dp[i][0][1]=(dp[i-1][0][1]+dp[i-1][1][1]+dp[i-1][2][1])%mod;//當前位置選L,同樣,但是注意連續三個L,要減去上上層選擇L的dp[i][1][0]=(dp[i-1][0][0]+dp[i-1][1][0]-dp[i-2][1][0]+sum_L0)%mod;//容斥了一下sum_L0=(dp[i-2][1][0]-sum_L0+mod)%mod;dp[i][1][1]=(dp[i-1][0][1]+dp[i-1][1][1]+dp[i-1][2][1]-dp[i-2][1][1]+sum_L1)%mod;//再容斥了一下sum_L1=(dp[i-2][1][1]-sum_L1+mod)%mod;//當前位置選A,只能從上一層沒有A的地方來dp[i][2][1]=(dp[i-1][0][0]+dp[i-1][1][0])%mod;}return (dp[n-1][0][0]+dp[n-1][0][1]+dp[n-1][1][0]+dp[n-1][1][1]+dp[n-1][2][1])%mod;}
};
總結
以上是生活随笔為你收集整理的Leetcode 552.学生出勤记录‖ 动态规划+容斥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Leetcode 526.优美的排列 二
- 下一篇: BorderDet(论文解读)