本科团队例会分享1 多米诺与托米诺平铺问题 c语言

题目

题目来源

leetcode第790题.

题目描述

有两种形状的瓷砖:一种是 2 x 1 的多米诺形,另一种是形如 “L” 的托米诺形。两种形状都可以旋转。
多米诺和托米诺
给定整数 n ,返回可以平铺 2 x n 的面板的方法的数量。返回对 10^9 + 7 取模 的值。平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同,当且仅当面板上有四个方向上的相邻单元中的两个,使得恰好有一个平铺有一个瓷砖占据两个正方形。

我的解法与讲解(动态规划)

二维数组解

dp[i][4] 代表的是第i列的状态,dp[i][0]代表这一列上下都没有被铺,1代表上面一块没有没铺,2代表下面一块没有被铺,3代表上下全被铺满。
dp[i]的状态只与dp[i-1]的状态有关
解法图
0->0与3->3会多考虑一种,所以要去掉其中之一。据此可做出转移方程

int numTilings(int n){
    long dp[n + 1][4];
    long MOD = 1000000007;
    dp[1][0] = 1;
    dp[1][1] = 0;
    dp[1][2] = 0;
    dp[1][3] = 1;
    for(int i = 2; i <= n; i++){
        dp[i][0] = (dp[i - 1][3]) % MOD;
        dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % MOD;
        dp[i][2] = (dp[i - 1][0] + dp[i - 1][1]) % MOD;
        dp[i][3] = (dp[i - 1][0] + dp[i - 1][3] + dp[i - 1][2] + dp[i - 1][1]) % MOD;
    }
    return (int)dp[n][3];
}

优化

空间优化

c语言好像不能直接拷贝数组,其它语言可用两个一维数组替代二维数组,一个数组存储

最优解

dp[i]代表0到i列铺满的方法数量。
递推:0 ~ n-1列铺好,加个多米诺推到n;0 ~ n-2列铺好,就是n-1没铺好,不能是两个竖着的多米诺,只能是两个横着的多米诺。我们在通过dp(i)平铺dp(n)时,i+1~n-1列不能有完成拼好的,否则就重复计算了。
0 ~ n-3列铺好推到n,说明倒数三列状态都不能是3。就是两个L型的托米诺,
dp(n-4) 两个托米诺夹一个多米诺
dp(n-5) 两个托米诺夹两个多米诺
…….
托米诺是能倒过来的,所以有托米诺的就会有两种情况。
由此推出公式dp(n) = dp(n-1) + dp(n-2)+2*(dp(n-3)+dp(n-4)+dp(n-5)……dp(1));
得到dp(n-1)=dp(n-2)+dp(n-3)+2*(dp(n-4)+dp(n-5)+……dp(1));
将两式相减得到dp(n)=2*dp(n-1)+dp(n-3);

int numTilings(int n){
    if(n <= 2){
        return n;
    }
    long dp[n+1];
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 5;
    long MOD = 1000000007;
    
    for(int i = 4; i <= n; i++){
        dp[i] = (2 * dp[i - 1] + dp[i - 3]) % MOD;
    }
    return (int)dp[n];
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值