leetcode790.多米诺和托米诺平铺

题目大意

有两种形状的瓷砖:一种是 2x1 的多米诺形,另一种是形如 “L” 的托米诺形。两种形状都可以旋转。

XX  <- 多米诺

XX  <- "L" 托米诺
X

给定 N 的值,有多少种方法可以平铺 2 x N 的面板?返回值 mod 10^9 + 7。

(平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同,当且仅当面板上有四个方向上的相邻单元中的两个,使得恰好有一个平铺有一个瓷砖占据两个正方形。)

示例:
输入: 3
输出: 5
解释: 
下面列出了五种不同的方法,不同字母代表不同瓷砖:
XYZ XXZ XYY XXY XYY
XYZ YYZ XZZ XYY XXY

解题思路

寻找递推公式。
对于任意n来说,要想全部平铺:

  • f(n-1)全部平铺的情况下,加上一个2*1的块即可,1种方式;
  • f(n-2)全部平铺的情况下,加上两个横着的12块即可,一种方式(注意,这里不能加入两个竖着的21块,因为当n-2完成后,如果加上一个竖着的块,那么n-1也全部平铺完成了,和f(n-1)就重复计算了,因此n-2时仅有一种方式);
  • f(n-3)全部平铺的情况下,只能通过放置两个’L’块平铺,两个L块可以上下颠倒,因此有2种方式从f(n-3)平铺成f(n)。注意:如果放置一个21块,则相当于重复计算了f(n-2),如果放置两个12块,则相当于重复计算了f(n-1)。
  • 综上所述,我们在通过f(x)平铺f(n)时,x+1~n-1列不能有完成拼好的,否则就重复计算了

因此:从f(x)平铺f(n)时,我们先放置一个L型块,然后x+1~n-1列全部用12的块填充,这样就会使得每一列都是错位的。填充完毕后,n-1列中有1个格子被填充了,另一个格子空着,同时第n列空着。此时再用另一个L块填充即可。 (对这种方法上下翻转可以形成另一种方案,因此需要2)

递推公式为:f(n)=f(n-1)+f(n-2)+2*(f(n-3)+…+f(0))。 另一方面f(n-1)=f(n-2)+f(n-3)+2*(f(n-4)+…+f(0))。将第二个公式带入第一个公式中,化简得到:f(n)=2*f(n-1)+f(n-3)

注意:代码中可以仅通过几个变量来完成计算

class Solution {
public:
    int numTilings(int N) {
    	if (N <= 1)
    		return 1;
    	if (N == 2)
    		return 2;

    	vector<int> dp(N + 1, 0);
    	dp[0] = 1;
    	dp[1] = 1;
    	dp[2] = 2;

    	for (int i = 3; i <=N; ++i)
    	{
    		dp[i] = (2 * dp[i - 1] % 1000000007 + dp[i - 3] % 1000000007) % 1000000007;
    	}

    	return dp.back();
    }
};

猜你喜欢

转载自blog.csdn.net/qq_41092190/article/details/106937900