这是2021-9-5的一道周赛题,当时以为是要用差分数组,但是发现这么做复杂度太高了,并且容易写错,看了题解的dalao才恍然大悟,就是一道普通但很难想到的dp(自己tcl /(ㄒoㄒ)/~~)
原题:[5865. 访问完所有房间的第一天](https://leetcode-cn.com/problems/first-day-where-you-have-been-in-all-the-rooms/)
解释在注释
// dp[i]代表可以离开i的总天数的和, 下文dp的下标从1开始
// 主要分两种情况:
// 1、当前的nextVisit是自己,那么就是直接可以从前一天到今天,那么 dp[i] = dp[i-1] + 2
// 2、当天的nextVisit是之前的房间j,那么就需要重新再走一次j~i-1, 根据前缀和,再走一次的天数是dp[i-1]-dp[nextVisit[i-1]],然后再加上之前走过的和自己的2次:
// dp[i] = dp[i-1]-dp[nextVisit[i-1]] + dp[i-1] + 2
// 上代码
#define ll long long
class Solution {
public:
int firstDayBeenInAllRooms(vector<int>& nextVisit) {
ll MOD = 1e9+7;
int n = nextVisit.size();
vector<ll> dp(n+1, 0);
for(int i=1; i<=n-1; i++){
// 公式里面MOD的原因是前面mod的结果可能比当前小,所以每一步都要加上mod防止出现负数
if(nextVisit[i-1]==i-1)
dp[i] = (dp[i-1]+2+MOD)%MOD;
else
dp[i] = (dp[i-1]-dp[nextVisit[i-1]] + dp[i-1] + 2+MOD) % MOD;
}
return dp[n-1];
}
};