https://leetcode.com/problems/domino-and-tromino-tiling/description/
动手画画图,dp的方程应该不难想。(注意总结case数目这种,一定考虑怎么把Case归类,防止多次计数)。直接按dp方程写就是:
class Solution {
public:
int numTilings(int N) {
long long dp[N+5];
long long MOD = 1e9 + 7;
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= N; i ++) {
dp[i] = (dp[i-1] + dp[i-2]) % MOD;
for (int j = 3; j <= i; j++) {
dp[i] += (2*dp[i - j])%MOD;
dp[i] % MOD;
}
}
return dp[N] % MOD;
}
};
然后看到有O(n)的 https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116581/Detail-and-explanation-of-O(n)-solution-why-dpn2*dn-1+dpn-3
dp[n]=dp[n-1]+dp[n-2]+ 2*(dp[n-3]+…+d[0])
=dp[n-1]+dp[n-2]+dp[n-3]+dp[n-3]+2*(dp[n-4]+…+d[0])
=dp[n-1]+dp[n-3]+(dp[n-2]+dp[n-3]+2*(dp[n-4]+…+d[0]))
=dp[n-1]+dp[n-3]+dp[n-1]
=2*dp[n-1]+dp[n-3]
有意思的推导,然后O(1)就可以了。也有人通过试数据看出来的。
int numTilings(int N) {
int md=1e9;
md+=7;
vector<long long> v(1001,0);
v[1]=1;
v[2]=2;
v[3]=5;
if(N<=3)
return v[N];
for(int i=4;i<=N;++i){
v[i]=2*v[i-1]+v[i-3];
v[i]%=md;
}
return v[N];
}