POJ 2663

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84197654

这道题是一个 DP 题目。。涉及到了一部分的铺砖类型题的思路。。。

首先给你一个 3*n 的地面,用 2*1 的地砖铺满,问有多少种铺砖方式。。

这道题其实是 2*n 地面的升级版,所以会有一些特别。

首先如果 n 为 奇数 那么就肯定会出现铺不满的情况了。

n 为偶数时候。。我们通过简单的去算一下,发现存在一定规律

当 n > 4 时候

n为偶数,那么我们那首先可以拆分一下

设 dp[ i ] 为 n = i 时方案数,去递推,发现 dp [ i - 2 ] 再多加上两个 1*3 的地面就构成了 dp [ i ] 那么 dp[ i ] = dp [ i-1 ] * dp [ 2 ]

但是 我们再想一下,这样似乎还不是最终形态啊。。

实际操作起来,我们发现了一种特殊情况:   就是 假设给你一个 3*4 的地砖,你完全可以构造出一种除了 dp[ 2 ] 排版以外的模式

我在网上找到了这种图片

  

就是后面那两种。。我们发现这种情况下,整个四个地砖是一体的。。(被几个 1*2 的地砖 粘在一起 了)

那么 我们发现 存在这种不可分割的小组合 而且最多只有两种排列方式

所以 dp [ i ] 还需要 加上 dp[ i - 4 ] * 2。。逆推下去的话 还得加上 dp[ i - 6 ] * 2

所以这道题我们需要了解一种信息就是 不可分割的模块。。如上图那种。。。

其余可分割的部分 交给 递推来处理,不可分割的部分 我们单独计算

所以综上

dp [ i ] = 3 * dp [ i - 2 ] + 2 *\sum dp[i - 2*k] (k >= 2 && k<= i / 2)

构造出式子。。这道题就解决了。。

很经典的一道题

以下为AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long int
ll n;
ll dp[35];
int main()
{
    memset(dp,0,sizeof(dp));
    dp[0]=1,dp[2]=3;
    for(int i=4;i<=30;i+=2)
    {
        dp[i]=dp[i-2]*3;
        for(int j=0;j<=i-4;j+=2)
        {
            dp[i]+=2*dp[j];
        }
    }
    while(~scanf("%lld",&n)&&n!=-1)
    {
        printf("%lld\n",dp[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/84197654
POJ