版权声明:本文为博主原创文章,未经博主允许不得转载。 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 *
构造出式子。。这道题就解决了。。
很经典的一道题
以下为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;
}