算法作业_19(2017.5.3第十一周)

来源:互联网 发布:上瘾网络剧美拍 编辑:程序博客网 时间:2024/06/03 19:07

552. Student Attendance Record II

Given a positive integer n, return the number of all possible attendance records with length n, which will be regarded as rewardable. The answer may be very large, return it after mod 109 + 7.

A student attendance record is a string that only contains the following three characters:

  1. 'A' : Absent.
  2. 'L' : Late.
  3. 'P' : Present.

给定一个正整数n,返回长度为n的序列的个数,这个序列是所有可能出席的记录,也就是被认为可以奖赏的。答案可能很大,返回值模上10的9次 + 7。学生出席记录的字符串由‘A’,'L','P'三种字符构成,分别代表出席,迟到和缺席。一条被认为是可奖赏的记录不能超过一次缺席(A)和不能超过连续两个迟到(L)

思路:注意到题目中告诉我们答案可能很大,所以不能采用穷举法或者递归的方法。要用动态规划的方法来解。首先看题目的要求,一条记录当中最多能出现一个A和连续两个L,所以答案跟这两个变量都相关,另外,答案是根据输入的n来输出可能性,所以也与n有关。因此,要用一个三维数组dp[n][i][j]来记录答案,表示长度为n,包含i个A和以连续j个L结尾的字符串所有可能的个数。显然i的取值是0和1,j的取值是0,1,2。因此可以这样初始化dp[1]:dp[1][0][0] = 1; dp[1][0][1] = 1; dp[1][0][2] = 0; dp[1][1][0] = 1; dp[1][1][1] =

0; dp[1][1][2] = 0。  因为字符串长度仅为1,所以出现两个L,一个L和一个A的情况不会出现。接下来状态转移。

状态转移有很多种可能,如果长度为i时,没有出现一个A并且结尾不是L的情况,可以推出长尾为i-1时,也没有出现一个A和结尾不是L,dp[i][0][0] = sum(dp[i-1][0]); 没有出现一个A并且以一个L结尾的情况,可以推出长尾为i-1时,也没有出现一个A和结尾不是L,dp[i][0][1] = dp[i-1][0][0]; 没有出现一个A并且以两个L结尾的情况,可以推出长尾为i-1时,也没有出现一个A和结尾是一个L,dp[i][0][2] = dp[i-1][0][1];  出现了一个A和结尾不是L的情况,可以推出长尾为i-1时,可能没有出现一个A或者出现过一个A并且结尾不是L,dp[i][1][0] = sum(dp[i-1][0]) + sum(dp[i-1][1]); 剩余两种情况与上面类似。

public class Solution {    private final int MOD = 1000000007;    public long sum(int[] nums) {        long ans = 0;        for (int n : nums) ans += n;        return ans % MOD;    }        public int checkRecord(int n) {        int dp[][] = {{1, 1, 0}, {1, 0, 0}};        for (int i = 2; i <= n; i++) {            int ndp[][] = {{0, 0, 0}, {0, 0, 0}};            ndp[0][0] = (int)sum(dp[0]);            ndp[0][1] = dp[0][0];            ndp[0][2] = dp[0][1];            ndp[1][0] = (int)((sum(dp[0]) + sum(dp[1])) % MOD);            ndp[1][1] = dp[1][0];            ndp[1][2] = dp[1][1];            dp = ndp;        }        return (int)((sum(dp[0]) + sum(dp[1])) % MOD);    }}



0 0
原创粉丝点击